{
Этот исходный код является частью проекта ПВТ-ОО.
Copyright © 2021 Малик Разработчик
Это свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она может быть полезна,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЁННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.
}
unit ru.malik.elaborarer.avt.tree;
{$MODE DELPHI}
interface
uses
pascalx.lang,
pascalx.utils,
ru.malik.elaborarer.avt.programme,
ru.malik.elaborarer.avt.lexer,
ru.malik.elaborarer.avt.constant,
ru.malik.elaborarer.avt.table;
{$ASMMODE INTEL,CALLING REGISTER,TYPEINFO ON}
{%region pulic }
type
AVTCodeBuilder = class;
AVTCodeBuilder = class(AVTTableBuilder)
private
class procedure defineSubnodesJumps(parentNode: AVTNode; code: AVTCode); static; overload;
class procedure defineSubnodesJumps(parentNode: AVTNode; code: AVTCode; jumpIsFalse, jumpIsTrue: AVTNode); static; overload;
class function getStartSubnode(code: AVTCode; parentNode, ifEmptyNode: AVTNode): AVTNode; static;
class function defineSubnodesOrder(parentNode: AVTNode; code: AVTCode; startFromOrder: int): int; static;
class function isRecursiveConstructorInvokation(constructorRef: AVTInstInit): boolean; static;
class function getCatchNode(currentNode: AVTNode; exceptionType: AVTTypeStructured): AVTNode; static;
class function getVariable(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod): AVTVariable; static;
private
fldResolvedVariable: AVTVariable;
fldTypeObjectRef: AVTTypeStructured;
fldTypeStructRef: AVTTypeStructured;
fldTypeThrowableRef: AVTTypeStructured;
procedure buildCode(methodRef: AVTMethod);
procedure needValue(currentNode: AVTNode; code: AVTCode);
procedure discardValue(currentNode: AVTNode; code: AVTCode);
procedure insertAfterConstructionInvoke(parentNode: AVTNode; code: AVTCode; pos, lineIndex: int);
procedure insertClinitInvoke(parentNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured; memberRef: AVTMember; lineIndex: int);
function insertClinitTryLockNode(rootNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured): AVTNode;
function insertSynchronizedNode(rootNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured): AVTNode;
function parsePostfix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers, isUseSuper, isImplicitPeriod: boolean): int;
function parsePrimary(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parsePrefix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseMultiplicative(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseAdditive(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseShift(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseRelational(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseEquality(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseBitAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseBitXor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseBitOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseBoolAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseBoolOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseConditional(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
function parseExpression(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean = false): int;
function parseLocal(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; variableAllowed: boolean = true): int;
function parseBlock(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseDo(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseIf(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseFor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseTry(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseWith(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseBreak(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseThrow(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseWhile(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseReturn(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseSwitch(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseContinue(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseSynchronized(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseStatement(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
function parseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType; overload;
function tryParseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType; overload;
function resolveName(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; pos: int): AVTItem; overload;
function insertIncrementCode(parentNode: AVTNode; code: AVTCode; typeOperandRef: AVTTypePrimitive; isIncrement: boolean; lineIndex: int): AVTNode;
function cast(currentNode: AVTNode; code: AVTCode; typeNewRef: AVTType): AVTNode; overload;
function getPrimitiveTypeForIntValue(value: int): AVTTypePrimitive;
public
procedure parseMethods(typeRef: AVTTypeStructured);
function getThrowableType(): AVTTypeStructured;
function getStructType(): AVTTypeStructured;
function getObjectType(): AVTTypeStructured;
end;
{%endregion}
implementation
{%region AVTCodeBuilder }
class procedure AVTCodeBuilder.defineSubnodesJumps(parentNode: AVTNode; code: AVTCode);
var
i: int;
len: int;
order: int;
instruction: int;
nextNode: AVTNode;
childNode0: AVTNode;
childNode1: AVTNode;
childNode2: AVTNode;
childNode3: AVTNode;
childNode4: AVTNode;
begin
instruction := parentNode.instruction;
case instruction of
AVT_IF, OPER_BOOL_COND: begin
len := parentNode.length;
if len > 2 then begin
childNode2 := parentNode[2];
if childNode2.order < 0 then exit;
end else begin
childNode2 := nil;
end;
nextNode := code[code.maxInstructionOrder(parentNode) + 1];
if len <= 2 then begin
defineSubnodesJumps(parentNode[0], code, nextNode, getStartSubnode(code, parentNode[1], nextNode));
end else begin
defineSubnodesJumps(parentNode[0], code, getStartSubnode(code, parentNode[3], nextNode), getStartSubnode(code, parentNode[1], nextNode));
childNode2.jumpDefault := nextNode;
end;
end;
AVT_DO: begin
childNode1 := parentNode[1];
nextNode := code[code.maxInstructionOrder(parentNode) + 1];
defineSubnodesJumps(childNode1, code, nextNode, getStartSubnode(code, parentNode[0], code[code.minInstructionOrder(childNode1)]));
end;
AVT_FOR: begin
len := parentNode.length;
childNode0 := parentNode[len - 4];
childNode1 := parentNode[len - 3];
childNode2 := parentNode[len - 2];
childNode3 := parentNode[len - 1];
nextNode := code[code.maxInstructionOrder(parentNode) + 1];
childNode0.jumpDefault := code[code.minInstructionOrder(childNode3)];
defineSubnodesJumps(childNode3, code, nextNode, getStartSubnode(code, childNode1, getStartSubnode(code, childNode2, childNode0.jumpDefault)));
end;
AVT_WHILE: begin
childNode0 := parentNode[0];
childNode1 := parentNode[1];
childNode2 := parentNode[2];
nextNode := code[code.maxInstructionOrder(parentNode) + 1];
childNode0.jumpDefault := code[code.minInstructionOrder(childNode2)];
defineSubnodesJumps(childNode2, code, nextNode, getStartSubnode(code, childNode1, childNode0.jumpDefault));
end;
AVT_SWITCH: begin
for i := 1 to parentNode.length - 1 do begin
childNode0 := parentNode[i];
case childNode0.instruction of
AVT_CASE: begin
parentNode.jumpCaseSetNode((childNode0.operand1 as AVTConstant).value.asInt, childNode0);
end;
AVT_DEFAULT: begin
parentNode.jumpDefault := childNode0;
end;
end;
end;
end;
AVT_BREAK, AVT_CONTINUE, AVT_RETURN: begin
len := parentNode.length;
childNode0 := parentNode.operand1 as AVTNode;
case instruction of
AVT_CONTINUE: begin
instruction := JUMP;
if childNode0.instruction = AVT_FOR then begin
childNode1 := childNode0[childNode0.length - 2];
childNode2 := childNode0.lastChild();
nextNode := getStartSubnode(code, childNode1, code[code.minInstructionOrder(childNode2)]);
end else begin
childNode1 := childNode0.lastChild();
nextNode := code[code.minInstructionOrder(childNode1)];
end;
end;
AVT_BREAK: begin
instruction := JUMP;
nextNode := code[code.maxInstructionOrder(childNode0) + 1];
end
else
childNode0 := code.root;
nextNode := childNode0.lastChild();
end;
childNode1 := parentNode;
repeat
childNode1 := childNode1.parent;
if childNode1.instruction <> AVT_TRY_BEGIN then continue;
childNode2 := childNode1.lastChild();
if childNode2.instruction <> AVT_FINALLY then continue;
if len = 0 then begin
childNode3 := code.insertNode(parentNode.parent, parentNode.index, parentNode.lineIndex, parentNode.dataType, instruction);
code.assignInstructionOrder(childNode3, parentNode.order + 1);
code.moveNode(parentNode, childNode3, 0);
parentNode.instruction := AVT_FINALLY_INVOKE;
parentNode.operand1 := childNode2;
parentNode := childNode3;
end else begin
childNode3 := parentNode.lastChild();
childNode4 := code.appendNode(parentNode, parentNode.lineIndex, parentNode.dataType, AVT_FINALLY_INVOKE, childNode2);
code.assignInstructionOrder(childNode4, code.maxInstructionOrder(childNode3) + 1);
end;
inc(len);
until childNode1 = childNode0;
parentNode.instruction := instruction;
parentNode.operand1 := nil;
parentNode.jumpDefault := nextNode;
if len > 0 then begin
childNode0 := parentNode[0];
childNode0.jumpDefault := code[childNode0.order + 1];
end;
end;
AVT_TRY_BEGIN: begin
parentNode[2].jumpDefault := code[code.maxInstructionOrder(parentNode) + 1];
end;
AVT_CATCH: begin
if parentNode.length > 0 then begin
childNode0 := parentNode.lastChild();
if childNode0.instruction = JUMP then begin
childNode0.jumpDefault := code[code.maxInstructionOrder(parentNode.parent) + 1];
end;
end;
parentNode.jumpDefault := code[parentNode.order + 1];
end;
AVT_THROW, AVT_FINALLY_RETURN: begin
{ нет переходов с throw и finallyReturn }
end
else
order := parentNode.order;
if order >= 0 then begin
parentNode.jumpDefault := code[order + 1];
end;
end;
end;
class procedure AVTCodeBuilder.defineSubnodesJumps(parentNode: AVTNode; code: AVTCode; jumpIsFalse, jumpIsTrue: AVTNode);
var
node: AVTNode;
begin
case parentNode.instruction of
OPER_BOOL_OR: begin
node := parentNode[1];
defineSubnodesJumps(parentNode[0], code, code[code.minInstructionOrder(node)], jumpIsTrue);
defineSubnodesJumps(node, code, jumpIsFalse, jumpIsTrue);
end;
OPER_BOOL_AND: begin
node := parentNode[1];
defineSubnodesJumps(parentNode[0], code, jumpIsFalse, code[code.minInstructionOrder(node)]);
defineSubnodesJumps(node, code, jumpIsFalse, jumpIsTrue);
end;
OPER_BOOL_NOT: begin
defineSubnodesJumps(parentNode[0], code, jumpIsTrue, jumpIsFalse);
end;
OPER_BOOL_COND: begin
code.clearInstructionOrder(parentNode[2]);
defineSubnodesJumps(parentNode[0], code, code[code.minInstructionOrder(parentNode[3])], code[code.minInstructionOrder(parentNode[1])]);
defineSubnodesJumps(parentNode[1], code, jumpIsFalse, jumpIsTrue);
defineSubnodesJumps(parentNode[3], code, jumpIsFalse, jumpIsTrue);
end
else
parentNode.setBooleanJump(jumpIsFalse, jumpIsTrue);
end;
end;
class function AVTCodeBuilder.getStartSubnode(code: AVTCode; parentNode, ifEmptyNode: AVTNode): AVTNode;
var
order: int;
begin
order := code.minInstructionOrder(parentNode);
if order < 0 then begin
result := ifEmptyNode;
exit;
end;
result := code[order];
end;
class function AVTCodeBuilder.defineSubnodesOrder(parentNode: AVTNode; code: AVTCode; startFromOrder: int): int;
var
i: int;
len: int;
begin
case parentNode.instruction of
AVT_WITH, AVT_IF, AVT_LABEL, AVT_DO, AVT_FOR, AVT_WHILE, AVT_BLOCK, OPER_BOOL_NOT, OPER_BOOL_AND, OPER_BOOL_OR, OPER_BOOL_COND, OPER_SCAL_PLUS, OPER_VECT_PLUS: begin
{ нумеруются только дочерние узлы, родительский узел НЕ нумеруется }
for i := 0 to parentNode.length - 1 do begin
startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
end;
end;
AVT_TRY_BEGIN, AVT_CATCH, AVT_FINALLY, AVT_ENTER, NEW_ARRAY_BY_ELEMENTS, NEW_CLASS, NEW_SERVICE, NEW_STRUCT: begin
{ узлы нумеруются как в управляющей конструкции: сначала – родительский узел, затем – дочерние узлы }
code.assignInstructionOrder(parentNode, startFromOrder);
inc(startFromOrder);
for i := 0 to parentNode.length - 1 do begin
startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
end;
end;
AVT_SWITCH, AVT_MONITOR_ENTER: begin
{ узлы нумеруются в следующем порядке: нулевой дочерний узел, родительский узел, остальные дочерние узлы }
len := parentNode.length;
if len <= 0 then begin
code.assignInstructionOrder(parentNode, startFromOrder);
inc(startFromOrder);
end else begin
startFromOrder := defineSubnodesOrder(parentNode[0], code, startFromOrder);
code.assignInstructionOrder(parentNode, startFromOrder);
inc(startFromOrder);
for i := 1 to parentNode.length - 1 do begin
startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
end;
end;
end
else
{ узлы нумеруются как в выражении: сначала – дочерние узлы, затем – родительский узел }
for i := 0 to parentNode.length - 1 do begin
startFromOrder := defineSubnodesOrder(parentNode[i], code, startFromOrder);
end;
code.assignInstructionOrder(parentNode, startFromOrder);
inc(startFromOrder);
end;
result := startFromOrder;
end;
class function AVTCodeBuilder.isRecursiveConstructorInvokation(constructorRef: AVTInstInit): boolean;
var
code: AVTCode;
node: AVTNode;
operand: _Object;
anotherConstructorRef: AVTInstInit;
begin
anotherConstructorRef := constructorRef;
repeat
code := anotherConstructorRef.code;
if code = nil then break;
node := code.root;
if node.length <= 0 then break;
node := node.firstChild();
if node.instruction <> INVOKE_SPECIAL then break;
operand := node.operand1;
if not(operand is AVTInstInit) then break;
anotherConstructorRef := AVTInstInit(operand);
if constructorRef = anotherConstructorRef then begin
result := true;
exit;
end;
until false;
result := false;
end;
class function AVTCodeBuilder.getCatchNode(currentNode: AVTNode; exceptionType: AVTTypeStructured): AVTNode;
var
i: int;
node: AVTNode;
child: AVTNode;
begin
node := currentNode.parent;
while node <> nil do begin
if node.instruction = AVT_TRY_BEGIN then for i := 3 to node.length - 1 do begin
child := node[i];
if (child.instruction = AVT_CATCH) and (child.operand1 as AVTVariable).valueType.isAssignableFrom(exceptionType) then begin
result := child;
exit;
end;
end;
node := node.parent;
end;
result := nil;
end;
class function AVTCodeBuilder.getVariable(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod): AVTVariable;
var
childNode: AVTNode;
associate: _Object;
begin
repeat
with parentNode.childs() do while hasMoreElements() do begin
childNode := nextElement().objectValue() as AVTNode;
case childNode.instruction of
DECLARE_VARIABLE, AVT_CATCH: begin
associate := childNode.operand1;
if (associate is AVTVariable) and (AVTVariable(associate).simpleName = simpleName) then begin
result := AVTVariable(associate);
exit;
end;
end;
end;
end;
parentNode := parentNode.parent;
until parentNode = nil;
result := methodRef.getArgument(simpleName);
end;
procedure AVTCodeBuilder.buildCode(methodRef: AVTMethod);
label
label0,
label1;
var
condition: boolean;
labelNeeded: boolean;
pos: int;
index: int;
order: int;
lineIndex: int;
labelNumber: int;
code: AVTCode;
root: AVTNode;
node: AVTNode;
child0: AVTNode;
child1: AVTNode;
child2: AVTNode;
expNode: AVTNode;
condNode: AVTNode;
source: AVTSource;
constant: AVTConstant;
argumentTypes: Vector;
foundInit: AVTMethod;
typeVoidRef: AVTType;
typeBooleanRef: AVTType;
typeRef: AVTTypeStructured;
typeDereferenceRef: AVTTypeStructured;
begin
code := methodRef.code;
if code = nil then exit;
root := code.root;
source := methodRef.source;
typeRef := methodRef.parentType;
pos := methodRef.implementationPosition;
typeVoidRef := getPrimitiveType(AVT_VOID);
typeBooleanRef := getPrimitiveType(AVT_BOOLEAN);
if not methodRef.isSynthetic() then begin
if pos < 0 then begin
if methodRef is AVTClassInit then begin
insertClinitTryLockNode(root, code, typeRef);
code.appendNode(root).setData(-1, typeVoidRef, AVT_LEAVE, methodRef.returnType);
end;
end else begin
root.setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_ENTER);
if methodRef is AVTInstInit then begin
{ вставка вызова конструктора }
lineIndex := source.getLexemeLineIndex(pos);
if source.getLexemeType(pos) = CHAR_COLON then begin
inc(pos);
if source.getLexemeType(pos) = AVT_SUPER then begin
typeDereferenceRef := typeRef.extends();
end else begin
typeDereferenceRef := typeRef;
end;
if typeDereferenceRef = nil then begin
raise AVTCompilerException.create('super can not be used in ' + itemToString(typeRef), source, pos);
end;
node := code.appendNode(root, lineIndex, typeVoidRef, INVOKE_SPECIAL, nil);
code.appendNode(node).setData(lineIndex, typeRef, LOAD_VARIABLE, methodRef.argumentThis);
inc(pos, 2); { переход через открывающую круглую скобку }
argumentTypes := Vector.create();
try
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
pos := parseExpression(node, code, methodRef, typeRef, source, pos, true);
expNode := node.lastChild();
needValue(expNode, code);
argumentTypes.append(ValueOfObject.create(expNode.dataType, false));
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;
foundInit := typeDereferenceRef.findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, pos);
if not foundInit.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The constructor ' + foundInit.parentType.simpleName + foundInit.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, pos);
end;
finally
argumentTypes.free();
end;
if not foundInit.isVisible(typeRef, typeRef) then begin
raise AVTCompilerException.create('The constructor ' + foundInit.parentType.simpleName + foundInit.argumentsToString() + ' is not visible', source, pos);
end;
for index := 0 to foundInit.getArgumentsCount() - 1 do begin
cast(node[index + 1], code, foundInit.getArgumentAt(index).valueType);
end;
node.operand1 := foundInit;
inc(pos); { переход через закрывающую круглую скобку }
if isRecursiveConstructorInvokation(AVTInstInit(methodRef)) then begin
raise AVTCompilerException.create('Recursive constructor invokation ' + foundInit.parentType.simpleName + foundInit.argumentsToString(), source, pos);
end;
end else begin
typeDereferenceRef := typeRef.extends();
if typeDereferenceRef <> nil then begin
foundInit := typeDereferenceRef.findMethod(SPECNAME_INST_INIT, nil, typeRef, pos);
if not foundInit.isConvertableArgumentTypes(nil) then begin
raise AVTCompilerException.create('Implicit super constructor ' + foundInit.parentType.simpleName + '() is undefined. Must explicitly invoke another constructor', source, pos);
end;
if not foundInit.isVisible(typeRef, typeRef) then begin
raise AVTCompilerException.create('Implicit super constructor ' + foundInit.parentType.simpleName + '() is not visible. Must explicitly invoke another constructor', source, pos);
end;
node := code.appendNode(root, lineIndex, typeVoidRef, INVOKE_SPECIAL, foundInit);
code.appendNode(node).setData(lineIndex, typeRef, LOAD_VARIABLE, methodRef.argumentThis);
end;
end;
end;
inc(pos); { переход через открывающую фигурную скобку }
if methodRef is AVTClassInit then begin
child0 := insertClinitTryLockNode(root, code, typeRef);
end else
if (methodRef.flags and FLAG_SYNCHRONIZED) <> 0 then begin
child0 := insertSynchronizedNode(root, code, methodRef, typeRef);
end else begin
child0 := root;
end;
repeat
case source.getLexemeType(pos) of
CHAR_CURLY_CLOSED: begin
code.appendNode(root).setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_LEAVE, methodRef.returnType);
break;
end;
AVT_END: begin
raise AVTCompilerException.create('"}" expected', source, pos);
end
else
pos := parseStatement(child0, code, methodRef, typeRef, source, pos);
end;
until false;
end;
end;
{ добавление узлов }
with code.nodes() do while hasMoreElements() do begin
node := nextElement().objectValue() as AVTNode;
case node.instruction of
OPER_BOOL_NOT, OPER_BOOL_AND, OPER_BOOL_OR: begin
index := node.index;
expNode := node.parent;
case expNode.instruction of
OPER_BOOL_COND, OPER_BOOL_NOT, OPER_BOOL_AND, OPER_BOOL_OR: begin
continue;
end;
AVT_DO, AVT_FOR, AVT_WHILE: begin
if index >= expNode.length - 1 then continue;
end;
AVT_IF: begin
if index <= 0 then continue;
end;
end;
lineIndex := node.lineIndex;
condNode := code.insertNode(expNode, index, lineIndex, typeBooleanRef, OPER_BOOL_COND);
code.moveNode(node, condNode, 0);
constant := AVTConstant.create(typeBooleanRef);
constant.value.asBoolean := true;
code.appendNode(condNode).setData(lineIndex, typeBooleanRef, LOAD_CONST, constant);
code.appendNode(condNode).setData(lineIndex, typeVoidRef, JUMP);
constant := AVTConstant.create(typeBooleanRef);
constant.value.asBoolean := false;
code.appendNode(condNode).setData(lineIndex, typeBooleanRef, LOAD_CONST, constant);
end;
AVT_ENTER: begin
insertClinitInvoke(node, code, typeRef, methodRef, node.lineIndex);
end;
LOAD_STATIC: begin
insertClinitInvoke(node, code, typeRef, node.operand1 as AVTMember, node.lineIndex);
end;
end;
end;
{ нумерация узлов }
defineSubnodesOrder(root, code, 0);
for index := code.length - 2 downto 0 do begin
node := code[index];
case node.instruction of
OPER_SCAL_E, OPER_SCAL_NE: begin
if (node.operand1 is AVTTypeStructured) and (node.length = 2) then begin
child1 := node[0];
child2 := node[1];
if (child1.order >= 0) and child1.isLoadNull() then begin
code.clearInstructionOrder(child1);
continue;
end;
if (child2.order >= 0) and child2.isLoadNull() then begin
code.clearInstructionOrder(child2);
continue;
end;
end;
end;
end;
end;
{ расстановка переходов }
index := 0;
node := root;
defineSubnodesJumps(node, code);
if node.length > 0 then repeat
child0 := node[index];
order := child0.order;
if (order < 0) or (order < code.length - 1) and (child0.jumpDefault = nil) then begin
defineSubnodesJumps(child0, code);
end;
if child0.length > 0 then begin
index := 0;
node := child0;
continue;
end;
inc(index);
while index >= node.length do begin
index := node.index + 1;
node := node.parent;
if node = nil then goto label0;
end;
until false;
label0:
{ оптимизация переходов }
{ --- не реализовано в этой версии, но обязательно должно быть реализовано в одной из следующих --- }
{ оптимизация переходов в try…finally }
repeat
condition := true;
with code.nodes() do while hasMoreElements() do with nextElement().objectValue() as AVTNode do if (instruction = AVT_TRY_BEGIN) and (child[3].instruction = AVT_FINALLY) then begin
child1 := child[1]; { instruction = AVT_TRY_END }
child0 := child1[0]; { instruction = AVT_FINALLY_INVOKE }
if (child0.order >= 0) and (child0.order > order + 1) and not code.isHasJumpsTo(child0) then begin
child2 := child[2]; { instruction = JUMP }
code.clearInstructionOrder(child0);
code.clearInstructionOrder(child2);
child0.jumpDefault := nil;
child1.jumpDefault := nil;
child2.jumpDefault := nil;
condition := false;
break;
end;
end;
until condition;
{ проверка обязательного возвращения значения }
if not methodRef.returnType.isVoid() then with code.instructions() do while hasMoreElements() do begin
node := nextElement().objectValue() as AVTNode;
if node.instruction = AVT_RETURN then begin
child0 := code[node.order + 1];
if child0.instruction = AVT_LEAVE then begin
code.clearInstructionOrder(node);
code.replaceNode(node, child0);
break;
end;
continue;
end;
child0 := node.jumpDefault;
if (child0 <> nil) and (child0.instruction = AVT_LEAVE) then begin
raise AVTCompilerException.create('Missing return statement', source, pos);
end;
with node.jumpCaseValues() do while hasMoreElements() do begin
child0 := node.jumpCaseGetNode(nextElement().intValue());
if (child0 <> nil) and (child0.instruction = AVT_LEAVE) then begin
raise AVTCompilerException.create('Missing return statement', source, pos);
end;
end;
end;
{ проверка генерации исключений }
with code.instructions() do while hasMoreElements() do begin
child0 := nextElement().objectValue() as AVTNode;
typeDereferenceRef := nil;
case child0.instruction of
AVT_THROW: begin
typeDereferenceRef := child0[0].dataType as AVTTypeStructured;
node := getCatchNode(child0, typeDereferenceRef);
if node <> nil then begin
child0.jumpDefault := node;
continue;
end;
if methodRef.mightThrown(typeDereferenceRef) then continue;
end;
INVOKE_STATIC, INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
with (child0.operand1 as AVTMethod).throws() do while hasMoreElements() do begin
typeDereferenceRef := nextElement().objectValue() as AVTTypeStructured;
if (getCatchNode(child0, typeDereferenceRef) = nil) and not methodRef.mightThrown(typeDereferenceRef) then goto label1;
end;
continue;
end;
end;
label1:
if typeDereferenceRef <> nil then begin
raise AVTCompilerException.create('Unhandled exception type ' + itemToString(typeDereferenceRef), source.fileName, child0.lineIndex, 0);
end;
end;
{ расстановка меток }
labelNumber := 0;
with code.instructions() do while hasMoreElements() do begin
child0 := nextElement().objectValue() as AVTNode;
case child0.instruction of
AVT_CASE, AVT_DEFAULT, AVT_TRY_BEGIN, AVT_TRY_END, AVT_CATCH, AVT_FINALLY:
labelNeeded := true
else
labelNeeded := false;
order := child0.order - 1;
with code.instructions() do while hasMoreElements() do begin
child1 := nextElement().objectValue() as AVTNode;
condition := order = child1.order;
(* if(order == child1.order ? child1.instruction == AVT_SWITCH : child1.isJumpTo(child0)) { … } *)
if condition and (child1.instruction = AVT_SWITCH) or not condition and child1.isJumpTo(child0) then begin
labelNeeded := true;
break;
end;
end;
end;
if labelNeeded then begin
child0.labelNumber := labelNumber;
inc(labelNumber);
end;
end;
end;
procedure AVTCodeBuilder.needValue(currentNode: AVTNode; code: AVTCode);
var
lastNode: AVTNode;
typeReturnRef: AVTType;
foundMethod: AVTMethod;
foundProperty: AVTProperty;
begin
typeReturnRef := currentNode.dataType;
if (typeReturnRef = nil) or not typeReturnRef.isVoid() then exit;
case currentNode.instruction of
STORE_VARIABLE: begin
lastNode := currentNode.lastChild();
currentNode.dataType := (currentNode.operand1 as AVTVariable).valueType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1);
end;
STORE_STATIC: begin
lastNode := currentNode.lastChild();
currentNode.dataType := (currentNode.operand1 as AVTField).valueType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1);
end;
SET_FIELD: begin
lastNode := currentNode.lastChild();
currentNode.dataType := (currentNode.operand1 as AVTField).valueType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X1);
end;
SET_PROPERTY: begin
lastNode := currentNode.lastChild();
currentNode.dataType := (currentNode.operand1 as AVTProperty).valueType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X1);
end;
SET_ARRAY_ELEMENT: begin
lastNode := currentNode.lastChild();
currentNode.dataType := currentNode.operand1 as AVTType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X2);
end;
INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
foundMethod := currentNode.operand1 as AVTMethod;
if (foundMethod is AVTOperator) and (AVTOperator(foundMethod).operatorKind = SET_ARRAY_ELEMENT) then begin
lastNode := currentNode.lastChild();
currentNode.dataType := foundMethod.getArgumentAt(1).valueType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X2);
end else begin
foundProperty := foundMethod.linkedProperty;
if (foundProperty <> nil) and (foundProperty.writeSynthetic = foundMethod) then begin
lastNode := currentNode.lastChild();
currentNode.dataType := foundMethod.getArgumentAt(0).valueType;
code.appendNode(currentNode).setData(lastNode.lineIndex, getPrimitiveType(AVT_VOID), DUP1X1);
end;
end;
end;
end;
end;
procedure AVTCodeBuilder.discardValue(currentNode: AVTNode; code: AVTCode);
var
instruction: int;
lastNode: AVTNode;
checkNode: AVTNode;
deleteNode: AVTNode;
parentNode: AVTNode;
typeVoidRef: AVTType;
typeReturnRef: AVTType;
foundMethod: AVTMethod;
foundProperty: AVTProperty;
begin
typeReturnRef := currentNode.dataType;
if (typeReturnRef <> nil) and typeReturnRef.isVoid() then exit;
typeVoidRef := getPrimitiveType(AVT_VOID);
case currentNode.instruction of
OPER_INC_POST, OPER_INC_PRED: begin
currentNode.instruction := OPER_INCREMENT;
currentNode.dataType := typeVoidRef;
exit;
end;
OPER_DEC_POST, OPER_DEC_PRED: begin
currentNode.instruction := OPER_DECREMENT;
currentNode.dataType := typeVoidRef;
exit;
end;
STORE_VARIABLE, STORE_STATIC: begin
lastNode := currentNode.lastChild();
if lastNode.instruction = DUP1 then begin
code.removeNode(lastNode);
currentNode.dataType := typeVoidRef;
exit;
end;
if currentNode.length = 2 then begin
checkNode := currentNode[0];
lastNode := currentNode.lastChild();
if lastNode.instruction = OPER_TYPE_CAST then begin
lastNode := lastNode.firstChild();
end;
instruction := lastNode.instruction;
if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
deleteNode := lastNode.firstChild();
if deleteNode.instruction = DUP1 then begin
code.removeNode(deleteNode);
code.moveNode(checkNode, lastNode, 0);
currentNode.dataType := typeVoidRef;
exit;
end;
end;
end;
end;
SET_FIELD, SET_PROPERTY: begin
lastNode := currentNode.lastChild();
if lastNode.instruction = DUP1X1 then begin
code.removeNode(lastNode);
currentNode.dataType := typeVoidRef;
exit;
end;
if currentNode.length = 3 then begin
checkNode := currentNode[1];
lastNode := currentNode.lastChild();
if lastNode.instruction = OPER_TYPE_CAST then begin
lastNode := lastNode.firstChild();
end;
instruction := lastNode.instruction;
if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
deleteNode := lastNode.firstChild();
if deleteNode.instruction = DUP1X1 then begin
code.removeNode(deleteNode);
code.moveNode(checkNode, lastNode, 0);
currentNode.dataType := typeVoidRef;
exit;
end;
end;
end;
end;
SET_ARRAY_ELEMENT: begin
lastNode := currentNode.lastChild();
if lastNode.instruction = DUP1X2 then begin
code.removeNode(lastNode);
currentNode.dataType := typeVoidRef;
exit;
end;
if currentNode.length = 4 then begin
checkNode := currentNode[2];
lastNode := currentNode.lastChild();
if lastNode.instruction = OPER_TYPE_CAST then begin
lastNode := lastNode.firstChild();
end;
instruction := lastNode.instruction;
if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
deleteNode := lastNode.firstChild();
if deleteNode.instruction = DUP1X2 then begin
code.removeNode(deleteNode);
code.moveNode(checkNode, lastNode, 0);
currentNode.dataType := typeVoidRef;
exit;
end;
end;
end;
end;
INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
foundMethod := currentNode.operand1 as AVTMethod;
if (foundMethod is AVTOperator) and (AVTOperator(foundMethod).operatorKind = SET_ARRAY_ELEMENT) then begin
lastNode := currentNode.lastChild();
if lastNode.instruction = DUP1X2 then begin
code.removeNode(lastNode);
currentNode.dataType := typeVoidRef;
exit;
end;
if currentNode.length = 4 then begin
checkNode := currentNode[2];
lastNode := currentNode.lastChild();
if lastNode.instruction = OPER_TYPE_CAST then begin
lastNode := lastNode.firstChild();
end;
instruction := lastNode.instruction;
if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
deleteNode := lastNode.firstChild();
if deleteNode.instruction = DUP1X2 then begin
code.removeNode(deleteNode);
code.moveNode(checkNode, lastNode, 0);
currentNode.dataType := typeVoidRef;
exit;
end;
end;
end;
end else begin
foundProperty := foundMethod.linkedProperty;
if (foundProperty <> nil) and (foundProperty.writeSynthetic = foundMethod) then begin
lastNode := currentNode.lastChild();
if lastNode.instruction = DUP1X1 then begin
code.removeNode(lastNode);
currentNode.dataType := typeVoidRef;
exit;
end;
if currentNode.length = 3 then begin
checkNode := currentNode[1];
lastNode := currentNode.lastChild();
if lastNode.instruction = OPER_TYPE_CAST then begin
lastNode := lastNode.firstChild();
end;
instruction := lastNode.instruction;
if (instruction = OPER_VECT_ADD) or (instruction = OPER_SCAL_ADD) then begin
deleteNode := lastNode.firstChild();
if deleteNode.instruction = DUP1X1 then begin
code.removeNode(deleteNode);
code.moveNode(checkNode, lastNode, 0);
currentNode.dataType := typeVoidRef;
exit;
end;
end;
end;
end;
end;
end
end;
parentNode := code.insertNode(currentNode.parent, currentNode.index, currentNode.lineIndex, typeVoidRef, POP1);
code.moveNode(currentNode, parentNode, 0);
end;
procedure AVTCodeBuilder.insertAfterConstructionInvoke(parentNode: AVTNode; code: AVTCode; pos, lineIndex: int);
var
currentNode: AVTNode;
foundMethod: AVTMethod;
typeStructuredRef: AVTTypeStructured;
begin
typeStructuredRef := getObjectType();
foundMethod := typeStructuredRef.findMethod('afterConstruction', nil, typeStructuredRef, pos);
if foundMethod <> nil then begin
currentNode := code.appendNode(parentNode, lineIndex, foundMethod.returnType, INVOKE_VIRTUAL, foundMethod);
code.appendNode(currentNode).setData(lineIndex, getPrimitiveType(AVT_VOID), DUP1);
end;
end;
procedure AVTCodeBuilder.insertClinitInvoke(parentNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured; memberRef: AVTMember; lineIndex: int);
var
memberType: TClass;
staticMethod: AVTClassInit;
typeTargetRef: AVTTypeStructured;
begin
memberType := memberRef.classType();
typeTargetRef := memberRef.parentType;
if (memberType = AVTMethod) and memberRef.isStatic() or (memberType = AVTInstInit) or (memberType = AVTField) and (typeRef <> typeTargetRef) then begin
with typeTargetRef.members(SPECNAME_CLASS_INIT) do if hasMoreElements() then begin
staticMethod := nextElement().objectValue() as AVTClassInit;
code.insertNode(parentNode, 0).setData(lineIndex, getPrimitiveType(AVT_VOID), INVOKE_STATIC, staticMethod);
end;
end;
end;
function AVTCodeBuilder.insertClinitTryLockNode(rootNode: AVTNode; code: AVTCode; typeRef: AVTTypeStructured): AVTNode;
var
i: int;
child0: AVTNode;
child1: AVTNode;
child2: AVTNode;
child3: AVTNode;
child4: AVTNode;
child5: AVTNode;
childResult: AVTNode;
typeVoidRef: AVTType;
typeBooleanRef: AVTType;
begin
(*
root
void if <== child0
boolean clinitTryLock(typeRef)
void {…} <== child1
void tryBegin <== child2
void {…} <== childResult
void tryEnd <== child3
void finallyInvoke(child5) <== child4
void jump
void finally <== child5
void clinitUnlock
void finallyReturn
*)
typeVoidRef := getPrimitiveType(AVT_VOID);
typeBooleanRef := getPrimitiveType(AVT_BOOLEAN);
child0 := code.appendNode(rootNode, -1, typeVoidRef, AVT_IF);
code.appendNode(child0).setData(-1, typeBooleanRef, AVT_CLINIT_TRY_LOCK, typeRef);
child1 := code.appendNode(child0, -1, typeVoidRef, AVT_BLOCK);
child2 := code.appendNode(child1, -1, typeVoidRef, AVT_TRY_BEGIN);
child3 := code.appendNode(child2, -1, typeVoidRef, AVT_TRY_END);
child4 := code.appendNode(child3, -1, typeVoidRef, AVT_FINALLY_INVOKE, nil);
code.appendNode(child2).setData(-1, typeVoidRef, JUMP);
child5 := code.appendNode(child2, -1, typeVoidRef, AVT_FINALLY);
code.appendNode(child5).setData(-1, typeVoidRef, AVT_CLINIT_UNLOCK);
code.appendNode(child5).setData(-1, typeVoidRef, AVT_FINALLY_RETURN);
child4.operand1 := child5;
childResult := code.insertNode(child2, 0, -1, typeVoidRef, AVT_BLOCK);
for i := rootNode.length - 2 downto 0 do begin
code.moveNode(rootNode[i], childResult, 0);
end;
result := childResult;
end;
function AVTCodeBuilder.insertSynchronizedNode(rootNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured): AVTNode;
var
isStatic: boolean;
child0: AVTNode;
child1: AVTNode;
child2: AVTNode;
child3: AVTNode;
syncVar: AVTVariable;
typeVoidRef: AVTType;
typeClassRef: AVTTypeStructured;
constant: AVTConstant;
begin
isStatic := methodRef.isStatic();
if isStatic then begin
typeClassRef := getClassType();
constant := AVTConstant.create(typeClassRef);
constant.value.asClass := typeRef;
syncVar := methodRef.createMonitorVariable(typeClassRef);
end else begin
constant := nil;
syncVar := methodRef.createMonitorVariable(typeRef);
end;
typeVoidRef := getPrimitiveType(AVT_VOID);
child0 := code.appendNode(rootNode, -1, typeVoidRef, AVT_MONITOR_ENTER);
child1 := code.appendNode(child0, -1, typeVoidRef, DECLARE_VARIABLE, syncVar);
if isStatic then begin
code.appendNode(child1).setData(-1, constant.valueType, LOAD_CONST, constant);
end else begin
code.appendNode(child1).setData(-1, typeRef, LOAD_VARIABLE, methodRef.argumentThis);
end;
code.appendNode(child1).setData(-1, typeVoidRef, DUP1);
child1 := code.appendNode(child0, -1, typeVoidRef, AVT_TRY_BEGIN);
child2 := code.appendNode(child1, -1, typeVoidRef, AVT_TRY_END);
child3 := code.appendNode(child2, -1, typeVoidRef, AVT_FINALLY_INVOKE, nil);
code.appendNode(child1).setData(-1, typeVoidRef, JUMP);
child2 := code.appendNode(child1, -1, typeVoidRef, AVT_FINALLY);
child3.operand1 := child2;
child3 := code.appendNode(child2, -1, typeVoidRef, AVT_MONITOR_LEAVE);
code.appendNode(child3).setData(-1, syncVar.valueType, LOAD_VARIABLE, syncVar);
code.appendNode(child2).setData(-1, typeVoidRef, AVT_FINALLY_RETURN);
result := code.insertNode(child1, 0, -1, typeVoidRef, AVT_BLOCK);
end;
function AVTCodeBuilder.parsePostfix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers, isUseSuper, isImplicitPeriod: boolean): int;
var
isPeriod: boolean;
isWriteOnly: boolean;
i: int;
base: int;
lineIndex: int;
lexemeType: int;
operatorPos: int;
instruction: int;
staticContext: int;
simpleName: AnsiString;
operand: _Object;
argumentTypes: Vector;
childNode: AVTNode;
currentNode: AVTNode;
compoundNode: AVTNode;
expressionNode: AVTNode;
oldConstant: AVTConstant;
newConstant: AVTConstant;
foundClinit: AVTClassInit;
foundMember: AVTMember;
foundField: AVTField;
foundProperty: AVTProperty;
foundOperator: AVTOperator;
foundMethod: AVTMethod;
typeParsedRef: AVTType;
typeReturnRef: AVTType;
typeElementRef: AVTType;
typeIntRef: AVTTypePrimitive;
typeVoidRef: AVTTypePrimitive;
typeDereferenceRef: AVTTypeStructured;
begin
repeat
lexemeType := source.getLexemeType(pos);
if isUseSuper and (lexemeType <> CHAR_PERIOD) and (lexemeType <> CHAR_PARENTH_OPENED) and (lexemeType <> CHAR_BRACKET_OPENED) then begin
raise AVTCompilerException.create('Syntax error on "super", error in expression', source, pos);
end;
isPeriod := false;
if isImplicitPeriod then begin
isPeriod := true;
end else
if lexemeType = CHAR_PERIOD then begin
isPeriod := true;
inc(pos);
end;
operatorPos := pos;
childNode := parentNode.lastChild();
typeReturnRef := childNode.dataType;
if isPeriod then begin
if (typeReturnRef <> nil) and not(typeReturnRef is AVTTypeStructured) then begin
raise AVTCompilerException.create('The type ' + typeReturnRef.fullName + ' can not be dereferenced', source, pos);
end;
if childNode.instruction = AVT_CLASS then begin
typeDereferenceRef := childNode.operand1 as AVTTypeStructured;
staticContext := -1; { это точно статичный контекст }
end else begin
typeDereferenceRef := AVTTypeStructured(typeReturnRef);
if isImplicitPeriod then begin
staticContext := 1; { неопределённый контекст }
end else begin
staticContext := 0; { это точно инстанционный контекст }
end;
end;
if typeDereferenceRef = nil then begin
raise AVTCompilerException.create('The type null can not be dereferenced', source, pos);
end;
case source.getLexemeType(pos) of
AVT_OPERATOR: begin
simpleName := AVTOperator.operatorToSpecName(parseOperator(source, pos + 1));
pos := source.position - 1;
end;
LITR_NAME: begin
simpleName := source.getLexemeAnsiString(pos);
end
else
raise AVTCompilerException.create('Member name expected', source, pos);
end;
foundMember := resolveMember(typeDereferenceRef, simpleName, typeRef, operatorPos);
if foundMember is AVTField then begin
foundField := AVTField(foundMember);
case staticContext of
-1: begin
if not foundField.isStatic() then begin
raise AVTCompilerException.create('Can not make a static reference to the non-static field ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
end;
oldConstant := foundField.valueConst;
if ((foundField.flags and (FLAG_STATIC or FLAG_FINAL)) = (FLAG_STATIC or FLAG_FINAL)) and (oldConstant <> nil) then begin
newConstant := AVTConstant.create();
newConstant.assign(oldConstant);
childNode.setData(childNode.lineIndex, newConstant.valueType, LOAD_CONST, newConstant);
end else begin
childNode.setData(childNode.lineIndex, foundField.valueType, LOAD_STATIC, foundField);
end;
end;
0: begin
if foundField.isStatic() then begin
raise AVTCompilerException.create('The static field ' + foundField.parentType.fullName + '.' + foundField.simpleName + ' should be accessed in a static way', source, pos);
end;
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundField.valueType, GET_FIELD, foundField);
code.moveNode(childNode, currentNode, 0);
end;
1: begin
if foundField.isStatic() then begin
oldConstant := foundField.valueConst;
if ((foundField.flags and FLAG_FINAL) = FLAG_FINAL) and (oldConstant <> nil) then begin
newConstant := AVTConstant.create();
newConstant.assign(oldConstant);
childNode.setData(childNode.lineIndex, newConstant.valueType, LOAD_CONST, newConstant);
end else begin
childNode.setData(childNode.lineIndex, foundField.valueType, LOAD_STATIC, foundField);
end;
end else begin
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundField.valueType, GET_FIELD, foundField);
code.moveNode(childNode, currentNode, 0);
end;
end;
end;
end else
if foundMember is AVTProperty then begin
foundProperty := AVTProperty(foundMember);
if staticContext = -1 then begin
raise AVTCompilerException.create('Can not make a static reference to the property ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
end;
foundMethod := foundProperty.readSynthetic;
if foundMethod = nil then begin
if source.getLexemeType(pos + 1) <> CHAR_EQUALS then begin
raise AVTCompilerException.create('The write-only property ' + foundProperty.simpleName + ' can not be accessed', source, pos);
end;
foundMethod := foundProperty.writeSynthetic;
if isUseSuper then begin
if foundMethod.isAbstract() then begin
raise AVTCompilerException.create('Can not directly write abstract property ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
end;
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
end else begin
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), SET_PROPERTY, foundProperty);
end;
end else begin
if isUseSuper then begin
if foundMethod.isAbstract() then begin
raise AVTCompilerException.create('Can not directly read abstract property ' + foundMember.simpleName + ' from the type ' + foundMember.parentType.fullName, source, pos);
end;
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
end else begin
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), foundProperty.valueType, GET_PROPERTY, foundProperty);
end;
end;
code.moveNode(childNode, currentNode, 0);
end else
if foundMember is AVTOperator then begin
inc(pos);
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
inc(pos);
currentNode := code.appendNode(parentNode);
argumentTypes := Vector.create();
try
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
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;
foundOperator := typeDereferenceRef.findMethod(simpleName, argumentTypes, typeRef, pos) as AVTOperator;
if not foundOperator.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' in the type ' + foundOperator.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
end;
finally
argumentTypes.free();
end;
if isUseSuper and not foundOperator.isVisible(typeRef, typeRef) or not isUseSuper and not foundOperator.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' in the type ' + foundOperator.parentType.fullName + ' is not visible', source, operatorPos);
end;
if isUseSuper and foundOperator.isAbstract() then begin
raise AVTCompilerException.create('Can not directly invoke abstract operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' from the type ' + foundOperator.parentType.fullName, source, operatorPos);
end;
for i := foundOperator.getArgumentsCount() - 1 downto 0 do begin
cast(currentNode[i], code, foundOperator.getArgumentAt(i).valueType);
end;
if staticContext = -1 then begin
raise AVTCompilerException.create('Can not make a static reference to the operator ' + AVTOperator.operatorToChar(foundOperator.operatorKind) + foundOperator.argumentsToString() + ' from the type ' + foundOperator.parentType.fullName, source, operatorPos);
end;
if isUseSuper or (foundOperator.visibility = AVT_PRIVATE) then begin
instruction := INVOKE_SPECIAL;
end else
if foundOperator.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
code.moveNode(childNode, currentNode, 0);
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundOperator.returnType, instruction, foundOperator);
end else
if foundMember is AVTMethod then begin
inc(pos);
{ СДЕЛАТЬ: if (foundMember.flags and FLAG_INTERRUPT) <> 0 then … }
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
inc(pos);
currentNode := code.appendNode(parentNode);
argumentTypes := Vector.create();
try
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
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;
foundMethod := typeDereferenceRef.findMethod(simpleName, argumentTypes, typeRef, pos);
if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
end;
finally
argumentTypes.free();
end;
if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
if isUseSuper and foundMethod.isAbstract() then begin
raise AVTCompilerException.create('Can not directly invoke abstract method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
end;
for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
cast(currentNode[i], code, foundMethod.getArgumentAt(i).valueType);
end;
case staticContext of
-1: begin
if not foundMethod.isStatic() then begin
raise AVTCompilerException.create('Can not make a static reference to the method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
end;
code.removeNode(childNode);
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, INVOKE_STATIC, foundMethod);
end;
0: begin
if foundMethod.isStatic() then begin
raise AVTCompilerException.create('The static method ' + foundMethod.simpleName + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName + ' should be accessed in a static way', source, operatorPos);
end;
if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
instruction := INVOKE_SPECIAL;
end else
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
code.moveNode(childNode, currentNode, 0);
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
end;
1: begin
if foundMethod.isStatic() then begin
code.removeNode(childNode);
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, INVOKE_STATIC, foundMethod);
end else begin
if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
instruction := INVOKE_SPECIAL;
end else
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
code.moveNode(childNode, currentNode, 0);
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
end;
end;
end;
end else begin
raise AVTCompilerException.create(simpleName + ' can not be resolved or is not a field', source, operatorPos);
end;
end else
case lexemeType of
CHAR_PARENTH_OPENED: begin
if not(typeReturnRef is AVTTypeStructured) then begin
raise AVTCompilerException.create('The operator () is not applicable for the type ' + itemToString(typeReturnRef), source, pos);
end;
typeDereferenceRef := AVTTypeStructured(typeReturnRef);
inc(pos);
currentNode := code.appendNode(parentNode);
argumentTypes := Vector.create();
try
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
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;
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(INVOKE_VIRTUAL), argumentTypes, typeRef, pos);
if foundMethod = nil then begin
raise AVTCompilerException.create('The operator () is not applicable for the type ' + typeDereferenceRef.fullName, source, operatorPos);
end;
if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator ()' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, pos);
end;
finally
argumentTypes.free();
end;
if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator ()' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
if isUseSuper and foundMethod.isAbstract() then begin
raise AVTCompilerException.create('Can not directly invoke abstract operator ()' + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
end;
for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
cast(currentNode[i], code, foundMethod.getArgumentAt(i).valueType);
end;
if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
instruction := INVOKE_SPECIAL;
end else
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
code.moveNode(childNode, currentNode, 0);
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
end;
CHAR_BRACKET_OPENED: begin
if typeReturnRef = nil then begin
raise AVTCompilerException.create('The operator [] is not applicable for the type null', source, pos);
end;
typeIntRef := getPrimitiveType(AVT_INT);
if typeReturnRef.isCompound() then begin
base := (typeReturnRef as AVTTypePrimitive).compoundBase;
typeElementRef := getPrimitiveType(base);
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeElementRef, GET_VECTOR_ELEMENT, typeReturnRef);
code.moveNode(childNode, currentNode, 0);
pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
raise AVTCompilerException.create('"]" expected', source, pos);
end;
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
if not typeIntRef.isConvertableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to int', source, operatorPos);
end;
expressionNode := cast(expressionNode, code, typeIntRef);
if expressionNode.instruction = LOAD_CONST then begin
oldConstant := expressionNode.operand1 as AVTConstant;
i := oldConstant.value.asInt;
if (i < 0) or (i >= AVTTypePrimitive(typeReturnRef).compoundLength) then begin
raise AVTCompilerException.create('Index [' + intToString(i) + '] out of bounds', source, pos);
end;
compoundNode := currentNode.firstChild();
if compoundNode.instruction = LOAD_CONST then begin
oldConstant := compoundNode.operand1 as AVTConstant;
newConstant := AVTConstant.create(typeElementRef);
case base of
AVT_BYTE:
newConstant.value.asByte := oldConstant.value.asByte8[i];
AVT_SHORT:
newConstant.value.asShort := oldConstant.value.asShort8[i];
AVT_INT, AVT_FLOAT:
newConstant.value.asInt := oldConstant.value.asInt8[i];
AVT_LONG, AVT_DOUBLE:
newConstant.value.asLong := oldConstant.value.asLong8[i];
end;
currentNode.setData(expressionNode.lineIndex, typeElementRef, LOAD_CONST, newConstant);
code.removeNode(expressionNode);
code.removeNode(compoundNode);
end;
end;
end else
if typeReturnRef is AVTTypeArray then begin
typeElementRef := AVTTypeArray(typeReturnRef).elementType;
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeElementRef, GET_ARRAY_ELEMENT, typeElementRef);
code.moveNode(childNode, currentNode, 0);
pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
raise AVTCompilerException.create('"]" expected', source, pos);
end;
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
if not typeIntRef.isConvertableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to int', source, pos);
end;
cast(expressionNode, code, typeIntRef);
end else
if typeReturnRef is AVTTypeStructured then begin
typeDereferenceRef := AVTTypeStructured(typeReturnRef);
currentNode := code.appendNode(parentNode);
code.moveNode(childNode, currentNode, 0);
pos := parseExpression(currentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
if source.getLexemeType(pos) <> CHAR_BRACKET_CLOSED then begin
raise AVTCompilerException.create('"]" expected', source, pos);
end;
isWriteOnly := false;
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeParsedRef, false));
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(GET_ARRAY_ELEMENT), argumentTypes, typeRef, pos);
if foundMethod = nil then begin
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), nil, typeRef, pos);
if foundMethod = nil then begin
raise AVTCompilerException.create('The operator [] is not applicable for the type ' + typeDereferenceRef.fullName, source, operatorPos);
end;
if source.getLexemeType(pos + 1) <> CHAR_EQUALS then begin
raise AVTCompilerException.create('The operator [] is undefined in the type ' + foundMethod.parentType.fullName, source, operatorPos);
end;
currentNode.setData(source.getLexemeLineIndex(pos + 1), foundMethod.returnType, INVOKE_VIRTUAL, foundMethod);
isWriteOnly := true;
end else
if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator []' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not applicable for the arguments ' + argumentTypes.toString(), source, pos);
end;
finally
argumentTypes.free();
end;
if not isWriteOnly then begin
if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator []' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
if isUseSuper and foundMethod.isAbstract() then begin
raise AVTCompilerException.create('Can not directly invoke abstract operator []' + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
end;
for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
cast(currentNode[i + 1], code, foundMethod.getArgumentAt(i).valueType);
end;
if isUseSuper or (foundMethod.visibility = AVT_PRIVATE) then begin
instruction := INVOKE_SPECIAL;
end else
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
currentNode.setData(source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
end;
end else begin
raise AVTCompilerException.create('The operator [] is not applicable for the type ' + itemToString(typeReturnRef), source, pos);
end;
end;
OPER_INCREMENT, OPER_DECREMENT: begin
typeVoidRef := getPrimitiveType(AVT_VOID);
instruction := childNode.instruction;
lineIndex := childNode.lineIndex;
case instruction of
LOAD_VARIABLE: begin
typeParsedRef := (childNode.operand1 as AVTVariable).valueType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
if lexemeType = OPER_INCREMENT then begin
childNode.instruction := OPER_INC_POST;
end else begin
childNode.instruction := OPER_DEC_POST;
end;
end;
LOAD_STATIC: begin
foundField := childNode.operand1 as AVTField;
if foundField.isFinal() then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, pos);
end;
typeParsedRef := foundField.valueType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
code.appendNode(childNode).setData(lineIndex, typeParsedRef, LOAD_STATIC, foundField);
currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
childNode.instruction := STORE_STATIC;
end;
GET_FIELD: begin
foundField := childNode.operand1 as AVTField;
if foundField.isFinal() then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, pos);
end;
typeParsedRef := foundField.valueType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, GET_FIELD, foundField);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X1);
childNode.instruction := SET_FIELD;
end;
GET_PROPERTY: begin
foundProperty := childNode.operand1 as AVTProperty;
if foundProperty.writeSynthetic = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, pos);
end;
typeParsedRef := foundProperty.valueType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, GET_PROPERTY, foundProperty);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X1);
childNode.instruction := SET_PROPERTY;
end;
GET_ARRAY_ELEMENT: begin
typeParsedRef := childNode.operand1 as AVTType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, GET_ARRAY_ELEMENT, typeParsedRef);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X2);
childNode.instruction := SET_ARRAY_ELEMENT;
end;
INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
operand := childNode.operand1;
if (operand is AVTOperator) and (AVTOperator(operand).operatorKind = GET_ARRAY_ELEMENT) then begin
typeParsedRef := AVTMethod(operand).returnType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
typeDereferenceRef := childNode[0].dataType as AVTTypeStructured;
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(AVTMethod(operand).getArgumentAt(0).valueType, false));
argumentTypes.append(ValueOfObject.create(typeParsedRef, false));
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, pos);
if (foundMethod = nil) or not foundMethod.isIdentityArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, pos);
end;
finally
argumentTypes.free();
end;
if isUseSuper and not foundMethod.isVisible(typeRef, typeRef) or not isUseSuper and not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator []=' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, instruction, operand);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X2);
if (instruction <> INVOKE_SPECIAL) or foundMethod.isAbstract() then begin
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
end;
childNode.setData(lineIndex, typeParsedRef, instruction, foundMethod);
end else begin
foundProperty := (operand as AVTMethod).linkedProperty;
if (foundProperty = nil) or (foundProperty.readSynthetic <> operand) then begin
raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, pos);
end;
typeParsedRef := foundProperty.valueType;
if not typeParsedRef.isNumeric() then begin
if lexemeType = OPER_INCREMENT then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeParsedRef), source, pos);
end;
end;
foundMethod := foundProperty.writeSynthetic;
if foundMethod = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, pos);
end;
currentNode := code.appendNode(childNode, lineIndex, typeParsedRef, instruction, operand);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
currentNode := insertIncrementCode(childNode, code, typeParsedRef as AVTTypePrimitive, lexemeType = OPER_INCREMENT, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeVoidRef, DUP1X1);
childNode.operand1 := foundMethod;
end;
end
else
raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, pos);
end;
end
else
break;
end;
isImplicitPeriod := false;
isUseSuper := false;
inc(pos);
until false;
result := pos;
end;
function AVTCodeBuilder.parsePrimary(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
var
isConstant: boolean;
isUseSuper: boolean;
isImplicitPeriod: boolean;
i: int;
kind: int;
index: int;
lineIndex: int;
dimensions: int;
lexemeType: int;
operatorPos: int;
simpleName: AnsiString;
argumentTypes: Vector;
constant: AVTConstant;
variable: AVTVariable;
typeResultRef: AVTType;
typeParsedRef: AVTType;
typeElementRef: AVTType;
typeIntRef: AVTTypePrimitive;
typeVoidRef: AVTTypePrimitive;
typeStructuredRef: AVTTypeStructured;
typeIntArray1dRef: AVTTypeArray;
arrayNode: AVTNode;
valueNode: AVTNode;
childNode: AVTNode;
currentNode: AVTNode;
expressionNode: AVTNode;
foundMethod: AVTMethod;
foundMember: AVTMember;
foundItem: AVTItem;
app: AVTProgramme;
begin
isUseSuper := false;
isImplicitPeriod := false;
lexemeType := source.getLexemeType(pos);
case lexemeType of
AVT_SUPER: begin
if ignoreInstanceMembers then begin
raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, pos);
end;
if methodRef.isStatic() then begin
raise AVTCompilerException.create('Can not use "super" in static context', source, pos);
end;
typeResultRef := typeRef.extends();
if typeResultRef = nil then begin
raise AVTCompilerException.create('super can not be used in ' + itemToString(typeRef), source, pos);
end;
variable := methodRef.argumentThis;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_VARIABLE, variable);
isUseSuper := true;
inc(pos);
end;
AVT_THIS: begin
if ignoreInstanceMembers then begin
raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, pos);
end;
if methodRef.isStatic() then begin
raise AVTCompilerException.create('Can not use "this" in static context', source, pos);
end;
variable := methodRef.argumentThis;
typeResultRef := variable.valueType;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_VARIABLE, variable);
inc(pos);
end;
AVT_NEW: begin
typeResultRef := parseType(parentNode, methodRef, typeRef, source, pos + 1);
operatorPos := source.position;
typeVoidRef := getPrimitiveType(AVT_VOID);
if typeResultRef.isArray() then begin
if source.getLexemeType(operatorPos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, operatorPos);
end;
inc(operatorPos);
with typeResultRef as AVTTypeArray do begin
typeElementRef := elementType;
makeCompilable();
end;
childNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeResultRef, NEW_ARRAY_BY_ELEMENTS, typeResultRef, nil);
index := 0;
if source.getLexemeType(operatorPos) <> CHAR_CURLY_CLOSED then repeat
lineIndex := source.getLexemeLineIndex(operatorPos);
constant := AVTConstant.create(getPrimitiveTypeForIntValue(index));
constant.value.asInt := index;
currentNode := code.appendNode(childNode);
currentNode.setData(lineIndex, typeVoidRef, SET_ARRAY_ELEMENT, typeElementRef);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
code.appendNode(currentNode).setData(lineIndex, constant.valueType, LOAD_CONST, constant);
operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
if not typeElementRef.isConvertableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to ' + itemToString(typeElementRef), source, operatorPos);
end;
cast(expressionNode, code, typeElementRef);
case source.getLexemeType(operatorPos) of
CHAR_COMMA: begin
inc(operatorPos);
end;
CHAR_CURLY_CLOSED: begin
break;
end
else
raise AVTCompilerException.create('"}" expected', source, operatorPos);
end;
inc(index);
until false;
index := childNode.length;
constant := AVTConstant.create(getPrimitiveTypeForIntValue(index));
constant.value.asInt := index;
childNode.operand2 := constant;
repeat
dec(index);
currentNode := childNode[index];
expressionNode := currentNode.lastChild();
if (expressionNode.instruction = LOAD_CONST) and (expressionNode.operand1 as AVTConstant).isDefaultValue() then begin
for i := currentNode.length - 1 downto 0 do begin
code.removeNode(currentNode[i]);
end;
code.removeNode(currentNode);
end;
until index = 0;
end else
if source.getLexemeType(operatorPos) = CHAR_BRACKET_OPENED then begin
if typeResultRef.isVoid() then begin
raise AVTCompilerException.create('The type void is an invalid type for array elements', source, operatorPos);
end;
index := 0;
app := programme;
typeIntRef := getPrimitiveType(AVT_INT);
childNode := code.appendNode(parentNode);
repeat
inc(index);
typeResultRef := app.getArrayOf(typeResultRef);
operatorPos := parseExpression(childNode, code, methodRef, typeRef, source, operatorPos + 1, ignoreInstanceMembers);
if source.getLexemeType(operatorPos) <> CHAR_BRACKET_CLOSED then begin
raise AVTCompilerException.create('"]" expected', source, operatorPos);
end;
expressionNode := childNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
if not typeIntRef.isConvertableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to int', source, operatorPos);
end;
cast(expressionNode, code, typeIntRef);
inc(operatorPos);
until (index >= 99) or (source.getLexemeType(operatorPos) <> CHAR_BRACKET_OPENED) or (source.getLexemeType(operatorPos + 1) = CHAR_BRACKET_CLOSED);
dimensions := index;
while (dimensions < 99) and (source.getLexemeType(operatorPos) = CHAR_BRACKET_OPENED) and (source.getLexemeType(operatorPos + 1) = CHAR_BRACKET_CLOSED) do begin
typeResultRef := app.getArrayOf(typeResultRef);
inc(operatorPos, 2);
inc(dimensions);
end;
(typeResultRef as AVTTypeArray).makeCompilable();
lineIndex := source.getLexemeLineIndex(pos);
if index = 1 then begin
childNode.setData(lineIndex, typeResultRef, NEW_ARRAY_BY_LENGTH, typeResultRef);
end else begin
childNode.setData(lineIndex, typeResultRef, NEW_MULTI_ARRAY, typeResultRef);
typeIntArray1dRef := app.getArrayOf(typeIntRef);
typeIntArray1dRef.makeCompilable();
constant := AVTConstant.create(getPrimitiveTypeForIntValue(index));
constant.value.asInt := index;
arrayNode := code.appendNode(childNode, lineIndex, typeIntArray1dRef, NEW_ARRAY_BY_ELEMENTS, typeIntArray1dRef, constant);
for i := index - 1 downto 0 do begin
valueNode := childNode[i];
currentNode := code.insertNode(arrayNode, 0, lineIndex, typeVoidRef, SET_ARRAY_ELEMENT, typeIntRef);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
constant := AVTConstant.create(typeIntRef);
constant.value.asInt := i;
code.appendNode(currentNode).setData(lineIndex, typeIntRef, LOAD_CONST, constant);
code.moveNode(valueNode, currentNode, 2);
end;
end;
dec(operatorPos);
end else
if typeResultRef.isCompound() then begin
if source.getLexemeType(operatorPos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, operatorPos);
end;
inc(operatorPos);
with typeResultRef as AVTTypePrimitive do begin
index := compoundLength - 1;
kind := compoundBase;
end;
isConstant := true;
typeElementRef := getPrimitiveType(kind);
childNode := code.appendNode(parentNode);
childNode.setData(source.getLexemeLineIndex(pos), typeResultRef, NEW_VECTOR, typeResultRef);
for i := 0 to index do begin
operatorPos := parseExpression(childNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
expressionNode := childNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
if not typeElementRef.isConvertableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to ' + itemToString(typeElementRef), source, operatorPos);
end;
expressionNode := cast(expressionNode, code, typeElementRef);
isConstant := isConstant and (expressionNode.instruction = LOAD_CONST);
if i < index then begin
if source.getLexemeType(operatorPos) <> CHAR_COMMA then begin
raise AVTCompilerException.create('"," expected', source, operatorPos);
end;
inc(operatorPos);
end;
end;
if source.getLexemeType(operatorPos) <> CHAR_CURLY_CLOSED then begin
raise AVTCompilerException.create('"}" expected', source, operatorPos);
end;
if isConstant then begin
constant := AVTConstant.create(typeResultRef);
for i := index downto 0 do begin
currentNode := childNode[i];
case kind of
AVT_BYTE:
constant.value.asByte8[i] := (currentNode.operand1 as AVTConstant).value.asByte;
AVT_SHORT:
constant.value.asShort8[i] := (currentNode.operand1 as AVTConstant).value.asShort;
AVT_INT, AVT_FLOAT:
constant.value.asInt8[i] := (currentNode.operand1 as AVTConstant).value.asInt;
AVT_LONG, AVT_DOUBLE:
constant.value.asLong8[i] := (currentNode.operand1 as AVTConstant).value.asLong;
end;
code.removeNode(currentNode);
end;
childNode.setData(childNode.lineIndex, childNode.dataType, LOAD_CONST, constant);
end;
end else
if typeResultRef.isAbstract() then begin
raise AVTCompilerException.create('Can not instantiate abstract type ' + typeResultRef.fullName, source, pos + 1);
end else
if typeResultRef.isStruct() then begin
typeStructuredRef := typeResultRef as AVTTypeStructured;
if source.getLexemeType(operatorPos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, operatorPos);
end;
inc(operatorPos);
lineIndex := source.getLexemeLineIndex(pos);
childNode := code.appendNode(parentNode);
childNode.setData(lineIndex, typeStructuredRef, NEW_STRUCT, typeStructuredRef);
currentNode := code.appendNode(childNode);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
argumentTypes := Vector.create();
try
if source.getLexemeType(operatorPos) <> CHAR_PARENTH_CLOSED then repeat
operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
case source.getLexemeType(operatorPos) of
CHAR_COMMA: begin
inc(operatorPos);
end;
CHAR_PARENTH_CLOSED: begin
break;
end
else
raise AVTCompilerException.create('")" expected', source, operatorPos);
end;
until false;
foundMethod := getStructType().findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, operatorPos);
if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
end;
finally
argumentTypes.free();
end;
if not foundMethod.isVisible(typeStructuredRef, typeRef) then begin
raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not visible', source, operatorPos);
end;
index := 0;
for i := 1 to currentNode.length - 1 do begin
cast(currentNode[i], code, foundMethod.getArgumentAt(index).valueType);
inc(index);
end;
currentNode.setData(lineIndex, foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
insertAfterConstructionInvoke(childNode, code, pos, lineIndex);
end else
if typeResultRef.isService() then begin
typeStructuredRef := typeResultRef as AVTTypeStructured;
if source.getLexemeType(operatorPos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, operatorPos);
end;
inc(operatorPos);
lineIndex := source.getLexemeLineIndex(pos);
childNode := code.appendNode(parentNode);
childNode.setData(lineIndex, typeStructuredRef, NEW_SERVICE, typeStructuredRef);
currentNode := code.appendNode(childNode);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
argumentTypes := Vector.create();
try
if source.getLexemeType(operatorPos) <> CHAR_PARENTH_CLOSED then repeat
operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
case source.getLexemeType(operatorPos) of
CHAR_COMMA: begin
inc(operatorPos);
end;
CHAR_PARENTH_CLOSED: begin
break;
end
else
raise AVTCompilerException.create('")" expected', source, operatorPos);
end;
until false;
foundMethod := typeStructuredRef.extends().findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, operatorPos);
if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
end;
finally
argumentTypes.free();
end;
if not foundMethod.isVisible(typeStructuredRef, typeRef) then begin
raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not visible', source, operatorPos);
end;
index := 0;
for i := 1 to currentNode.length - 1 do begin
cast(currentNode[i], code, foundMethod.getArgumentAt(index).valueType);
inc(index);
end;
currentNode.setData(lineIndex, foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
insertAfterConstructionInvoke(childNode, code, pos, lineIndex);
end else
if typeResultRef.isClass() then begin
typeStructuredRef := typeResultRef as AVTTypeStructured;
if source.getLexemeType(operatorPos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, operatorPos);
end;
inc(operatorPos);
lineIndex := source.getLexemeLineIndex(pos);
childNode := code.appendNode(parentNode);
childNode.setData(lineIndex, typeStructuredRef, NEW_CLASS, typeStructuredRef);
currentNode := code.appendNode(childNode);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
argumentTypes := Vector.create();
try
if source.getLexemeType(operatorPos) <> CHAR_PARENTH_CLOSED then repeat
operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
argumentTypes.append(ValueOfObject.create(expressionNode.dataType, false));
case source.getLexemeType(operatorPos) of
CHAR_COMMA: begin
inc(operatorPos);
end;
CHAR_PARENTH_CLOSED: begin
break;
end
else
raise AVTCompilerException.create('")" expected', source, operatorPos);
end;
until false;
foundMethod := typeStructuredRef.findMethod(SPECNAME_INST_INIT, argumentTypes, typeRef, operatorPos);
if not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not applicable for the arguments ' + argumentTypes.toString(), source, operatorPos);
end;
finally
argumentTypes.free();
end;
if not foundMethod.isVisible(typeStructuredRef, typeRef) then begin
raise AVTCompilerException.create('The constructor ' + foundMethod.parentType.simpleName + foundMethod.argumentsToString() + ' is not visible', source, operatorPos);
end;
index := 0;
for i := 1 to currentNode.length - 1 do begin
cast(currentNode[i], code, foundMethod.getArgumentAt(index).valueType);
inc(index);
end;
currentNode.setData(lineIndex, foundMethod.returnType, INVOKE_SPECIAL, foundMethod);
insertAfterConstructionInvoke(childNode, code, pos, lineIndex);
end else begin
raise AVTCompilerException.create('Can not instantiate the type ' + typeResultRef.fullName, source, pos + 1);
end;
if (typeResultRef.classType() = AVTTypeStructured) and (source.getLexemeType(operatorPos + 1) = CHAR_CURLY_OPENED) then begin
typeStructuredRef := AVTTypeStructured(typeResultRef);
inc(operatorPos, 2);
if source.getLexemeType(operatorPos) <> CHAR_CURLY_CLOSED then repeat
if source.getLexemeType(operatorPos) <> LITR_NAME then begin
raise AVTCompilerException.create('Field name expected', source, operatorPos);
end;
lineIndex := source.getLexemeLineIndex(operatorPos);
simpleName := source.getLexemeAnsiString(operatorPos);
foundMember := resolveMember(typeStructuredRef, simpleName, typeRef, operatorPos);
if foundMember is AVTField then begin
if foundMember.isStatic() or foundMember.isFinal() then begin
raise AVTCompilerException.create(simpleName + ' must be a non-static and non-final field', source, operatorPos);
end;
typeElementRef := AVTField(foundMember).valueType;
currentNode := code.appendNode(childNode);
currentNode.setData(lineIndex, typeVoidRef, SET_FIELD, foundMember);
end else
if foundMember is AVTProperty then begin
if AVTProperty(foundMember).writeSynthetic = nil then begin
raise AVTCompilerException.create(simpleName + ' must be a writable property', source, operatorPos);
end;
typeElementRef := AVTProperty(foundMember).valueType;
currentNode := code.appendNode(childNode);
currentNode.setData(lineIndex, typeVoidRef, SET_PROPERTY, foundMember);
end else begin
raise AVTCompilerException.create(simpleName + ' can not be resolved or is not a field', source, operatorPos);
end;
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
inc(operatorPos);
if source.getLexemeType(operatorPos) <> CHAR_EQUALS then begin
raise AVTCompilerException.create('"=" expected', source, operatorPos);
end;
operatorPos := parseExpression(currentNode, code, methodRef, typeRef, source, operatorPos + 1, ignoreInstanceMembers);
expressionNode := currentNode.lastChild();
needValue(expressionNode, code);
typeParsedRef := expressionNode.dataType;
if not typeElementRef.isConvertableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeParsedRef) + ' to ' + itemToString(typeElementRef), source, operatorPos);
end;
cast(expressionNode, code, typeElementRef);
case source.getLexemeType(operatorPos) of
CHAR_COMMA: begin
inc(operatorPos);
end;
CHAR_CURLY_CLOSED: begin
break;
end
else
raise AVTCompilerException.create('"}" expected', source, operatorPos);
end;
until false;
end;
pos := operatorPos + 1;
end;
AVT_NULL: begin
constant := AVTConstant.create(nil);
constant.value.isNull := true;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, LOAD_CONST, constant);
inc(pos);
end;
CHAR_PARENTH_OPENED: begin
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
needValue(parentNode.lastChild(), code);
inc(pos);
end;
LITR_NAME, AVT_VOID..AVT_DOUBLE8: begin
if lexemeType <> LITR_NAME then begin
foundItem := parseType(typeRef, pos);
operatorPos := source.position;
end else begin
simpleName := source.getLexemeAnsiString(pos);
foundItem := resolveName(simpleName, parentNode, methodRef, typeRef, pos);
if foundItem = nil then begin
raise AVTCompilerException.create(simpleName + ' can not be resolved to a variable', source, pos);
end;
if (foundItem is AVTPackage) or (foundItem is AVTType) then begin
foundItem := parseType(typeRef, pos);
operatorPos := source.position;
end else begin
operatorPos := pos + 1;
end;
end;
if foundItem is AVTVariable then begin
typeResultRef := AVTVariable(foundItem).valueType;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_VARIABLE, foundItem);
pos := operatorPos;
end else
if foundItem is AVTTypePrimitive then begin
if source.getLexemeType(operatorPos) <> CHAR_PERIOD then begin
raise AVTCompilerException.create('"." expected', source, operatorPos);
end;
inc(operatorPos);
if source.getLexemeType(operatorPos) <> AVT_CLASS then begin
raise AVTCompilerException.create('"class" expected', source, operatorPos);
end;
typeResultRef := getClassType();
constant := AVTConstant.create(typeResultRef);
constant.value.asClass := AVTTypePrimitive(foundItem);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
pos := operatorPos + 1;
end else
if foundItem is AVTTypeStructured then begin
if source.getLexemeType(operatorPos) <> CHAR_PERIOD then begin
raise AVTCompilerException.create('"." expected', source, operatorPos);
end;
inc(operatorPos);
case source.getLexemeType(operatorPos) of
AVT_CLASS: begin
if foundItem is AVTTypeArray then begin
AVTTypeArray(foundItem).makeCompilable();
end;
typeResultRef := getClassType();
constant := AVTConstant.create(typeResultRef);
constant.value.asClass := AVTTypeStructured(foundItem);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
pos := operatorPos + 1;
end;
AVT_SUPER: begin
if ignoreInstanceMembers then begin
raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, operatorPos);
end;
if methodRef.isStatic() then begin
raise AVTCompilerException.create('Can not use "super" in static context', source, operatorPos);
end;
typeStructuredRef := AVTTypeStructured(foundItem);
if typeRef.getImplements(typeStructuredRef) = nil then begin
raise AVTCompilerException.create('The type ' + itemToString(typeStructuredRef) + ' is not a supertype for ' + typeRef.simpleName, source, operatorPos);
end;
variable := methodRef.argumentThis;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeStructuredRef, LOAD_VARIABLE, variable);
isUseSuper := true;
pos := operatorPos + 1;
end;
LITR_NAME: begin
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, AVT_CLASS, foundItem);
pos := operatorPos - 1;
end
else
raise AVTCompilerException.create('Name of a static member expected', source, operatorPos);
end;
end else
if foundItem is AVTMember then begin
variable := fldResolvedVariable;
if variable = nil then begin
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, AVT_CLASS, typeRef);
end else begin
if ignoreInstanceMembers and (variable = methodRef.argumentThis) then begin
raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, operatorPos);
end;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), variable.valueType, LOAD_VARIABLE, variable);
end;
isImplicitPeriod := true;
end else begin
raise AVTCompilerException.create(foundItem.simpleName + ' can not be resolved to a variable', source, operatorPos);
end;
end;
AVT_OPERATOR: begin
kind := parseOperator(source, pos + 1);
foundItem := resolveName(AVTOperator.operatorToSpecName(kind), parentNode, methodRef, typeRef, pos);
if foundItem = nil then begin
raise AVTCompilerException.create('Operator ' + AVTOperator.operatorToChar(kind) + ' can not be resolved to an operator', source, pos);
end;
variable := fldResolvedVariable;
if variable = nil then begin
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), nil, AVT_CLASS, typeRef);
end else begin
if ignoreInstanceMembers and (variable = methodRef.argumentThis) then begin
raise AVTCompilerException.create('Can not refer to "this" nor "super" while explicitly invoking a constructor', source, operatorPos);
end;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), variable.valueType, LOAD_VARIABLE, variable);
end;
isImplicitPeriod := true;
end;
LITR_STRING: begin
typeResultRef := getStringType();
constant := AVTConstant.create(typeResultRef);
constant.value.asString := source.getLexemeUnicodeString(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_BOOLEAN: begin
typeResultRef := getPrimitiveType(AVT_BOOLEAN);
constant := AVTConstant.create(typeResultRef);
constant.value.asBoolean := source.getLexemeBoolean(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_CHAR: begin
typeResultRef := getPrimitiveType(AVT_CHAR);
constant := AVTConstant.create(typeResultRef);
constant.value.asChar := source.getLexemeChar(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_REAL: begin
typeResultRef := getPrimitiveType(AVT_REAL);
constant := AVTConstant.create(typeResultRef);
constant.value.asReal := source.getLexemeReal(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_BYTE: begin
typeResultRef := getPrimitiveType(AVT_BYTE);
constant := AVTConstant.create(typeResultRef);
constant.value.asByte := source.getLexemeByte(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_SHORT: begin
typeResultRef := getPrimitiveType(AVT_SHORT);
constant := AVTConstant.create(typeResultRef);
constant.value.asShort := source.getLexemeShort(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_INT: begin
typeResultRef := getPrimitiveType(AVT_INT);
constant := AVTConstant.create(typeResultRef);
constant.value.asInt := source.getLexemeInt(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_LONG: begin
typeResultRef := getPrimitiveType(AVT_LONG);
constant := AVTConstant.create(typeResultRef);
constant.value.asLong := source.getLexemeLong(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_FLOAT: begin
typeResultRef := getPrimitiveType(AVT_FLOAT);
constant := AVTConstant.create(typeResultRef);
constant.value.asFloat := source.getLexemeFloat(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end;
LITR_DOUBLE: begin
typeResultRef := getPrimitiveType(AVT_DOUBLE);
constant := AVTConstant.create(typeResultRef);
constant.value.asDouble := source.getLexemeDouble(pos);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeResultRef, LOAD_CONST, constant);
inc(pos);
end
else
raise AVTCompilerException.create('Error in expression', source, pos);
end;
result := parsePostfix(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers, isUseSuper, isImplicitPeriod);
end;
function AVTCodeBuilder.parsePrefix(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
i: int;
lineIndex: int;
lexemeType: int;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
argumentTypes: Vector;
stack: Vector;
dst: AVTConstant;
operand: _Object;
foundField: AVTField;
foundMethod: AVTMethod;
foundProperty: AVTProperty;
typeVoidRef: AVTType;
typeCastRef: AVTType;
typeReturnRef: AVTType;
typeOperandRef: AVTType;
typeDereferenceRef: AVTTypeStructured;
expressionNode: AVTNode;
currentNode: AVTNode;
item: AVTUnaryOperatorStackItem;
begin
stack := nil;
try
repeat
lexemeType := source.getLexemeType(pos);
case lexemeType of
OPER_BOOL_NOT, OPER_BIT_NOT, OPER_VECT_PACK, OPER_VECT_UNPCKL, OPER_VECT_UNPCKU: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, lexemeType)));
inc(pos);
end;
OPER_SCAL_ADD: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_SCAL_PLUS)));
inc(pos);
end;
OPER_SCAL_SUB: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_SCAL_MINUS)));
inc(pos);
end;
OPER_VECT_ADD: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_VECT_PLUS)));
inc(pos);
end;
OPER_VECT_SUB: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_VECT_MINUS)));
inc(pos);
end;
OPER_INCREMENT: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_INC_PRED)));
inc(pos);
end;
OPER_DECREMENT: begin
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(pos, OPER_DEC_PRED)));
inc(pos);
end;
CHAR_PARENTH_OPENED: begin
operatorPos := pos;
typeCastRef := tryParseType(parentNode, methodRef, typeRef, source, pos + 1);
pos := source.position;
if (typeCastRef = nil) or (source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED) then begin
pos := operatorPos;
break;
end;
if stack = nil then stack := Vector.create();
stack.append(ValueOfObject.create(AVTUnaryOperatorStackItem.create(operatorPos, OPER_TYPE_CAST, typeCastRef)));
inc(pos);
end
else
break;
end;
until false;
pos := parsePrimary(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
if stack <> nil then begin
expressionNode := parentNode.lastChild();
for i := stack.size() - 1 downto 0 do begin
item := stack.elementAt(i).objectValue() as AVTUnaryOperatorStackItem;
operatorPos := item.position;
operatorKind := item.operatorKind;
typeOperandRef := expressionNode.dataType;
if typeOperandRef = nil then begin
if operatorKind = OPER_TYPE_CAST then begin
typeCastRef := item.typeCast;
if typeCastRef is AVTTypeStructured then begin
expressionNode.dataType := typeCastRef;
continue;
end;
raise AVTCompilerException.create('Can not cast from null to ' + typeCastRef.fullName, source, operatorPos);
end;
end else
if typeOperandRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeOperandRef).primitiveKind;
instruction := expressionNode.instruction;
if instruction = LOAD_CONST then begin
dst := expressionNode.operand1 as AVTConstant;
if primitiveKind = AVT_CHAR then begin
primitiveKind := AVT_INT;
typeOperandRef := getPrimitiveType(AVT_INT);
dst.value.asInt := int(dst.value.asChar);
end;
case operatorKind of
OPER_BOOL_NOT: begin
if primitiveKind = AVT_BOOLEAN then begin
dst.value.asBoolean := not dst.value.asBoolean;
end else begin
goto label0;
end;
end;
OPER_BIT_NOT: begin
case primitiveKind of
AVT_BYTE:
byteBitNot(dst, dst);
AVT_BYTE2:
byte2BitNot(dst, dst);
AVT_BYTE4:
byte4BitNot(dst, dst);
AVT_BYTE8:
byte8BitNot(dst, dst);
AVT_SHORT:
shortBitNot(dst, dst);
AVT_SHORT2:
short2BitNot(dst, dst);
AVT_SHORT4:
short4BitNot(dst, dst);
AVT_SHORT8:
short8BitNot(dst, dst);
AVT_INT:
intBitNot(dst, dst);
AVT_INT2:
int2BitNot(dst, dst);
AVT_INT4:
int4BitNot(dst, dst);
AVT_INT8:
int8BitNot(dst, dst);
AVT_LONG:
longBitNot(dst, dst);
AVT_LONG2:
long2BitNot(dst, dst);
AVT_LONG4:
long4BitNot(dst, dst);
AVT_LONG8:
long8BitNot(dst, dst);
else
goto label0;
end;
end;
OPER_SCAL_PLUS: begin
case primitiveKind of
AVT_BYTE:
byteScalPlus(dst, dst);
AVT_BYTE2:
byte2ScalPlus(dst, dst);
AVT_BYTE4:
byte4ScalPlus(dst, dst);
AVT_BYTE8:
byte8ScalPlus(dst, dst);
AVT_SHORT:
shortScalPlus(dst, dst);
AVT_SHORT2:
short2ScalPlus(dst, dst);
AVT_SHORT4:
short4ScalPlus(dst, dst);
AVT_SHORT8:
short8ScalPlus(dst, dst);
AVT_INT:
intScalPlus(dst, dst);
AVT_INT2:
int2ScalPlus(dst, dst);
AVT_INT4:
int4ScalPlus(dst, dst);
AVT_INT8:
int8ScalPlus(dst, dst);
AVT_LONG:
longScalPlus(dst, dst);
AVT_LONG2:
long2ScalPlus(dst, dst);
AVT_LONG4:
long4ScalPlus(dst, dst);
AVT_LONG8:
long8ScalPlus(dst, dst);
AVT_FLOAT:
floatScalPlus(dst, dst);
AVT_FLOAT2:
float2ScalPlus(dst, dst);
AVT_FLOAT4:
float4ScalPlus(dst, dst);
AVT_FLOAT8:
float8ScalPlus(dst, dst);
AVT_DOUBLE:
doubleScalPlus(dst, dst);
AVT_DOUBLE2:
double2ScalPlus(dst, dst);
AVT_DOUBLE4:
double4ScalPlus(dst, dst);
AVT_DOUBLE8:
double8ScalPlus(dst, dst);
AVT_REAL:
realScalPlus(dst, dst);
else
goto label0;
end;
end;
OPER_SCAL_MINUS: begin
case primitiveKind of
AVT_BYTE:
byteScalMinus(dst, dst);
AVT_BYTE2:
byte2ScalMinus(dst, dst);
AVT_BYTE4:
byte4ScalMinus(dst, dst);
AVT_BYTE8:
byte8ScalMinus(dst, dst);
AVT_SHORT:
shortScalMinus(dst, dst);
AVT_SHORT2:
short2ScalMinus(dst, dst);
AVT_SHORT4:
short4ScalMinus(dst, dst);
AVT_SHORT8:
short8ScalMinus(dst, dst);
AVT_INT:
intScalMinus(dst, dst);
AVT_INT2:
int2ScalMinus(dst, dst);
AVT_INT4:
int4ScalMinus(dst, dst);
AVT_INT8:
int8ScalMinus(dst, dst);
AVT_LONG:
longScalMinus(dst, dst);
AVT_LONG2:
long2ScalMinus(dst, dst);
AVT_LONG4:
long4ScalMinus(dst, dst);
AVT_LONG8:
long8ScalMinus(dst, dst);
AVT_FLOAT:
floatScalMinus(dst, dst);
AVT_FLOAT2:
float2ScalMinus(dst, dst);
AVT_FLOAT4:
float4ScalMinus(dst, dst);
AVT_FLOAT8:
float8ScalMinus(dst, dst);
AVT_DOUBLE:
doubleScalMinus(dst, dst);
AVT_DOUBLE2:
double2ScalMinus(dst, dst);
AVT_DOUBLE4:
double4ScalMinus(dst, dst);
AVT_DOUBLE8:
double8ScalMinus(dst, dst);
AVT_REAL:
realScalMinus(dst, dst);
else
goto label0;
end;
end;
OPER_VECT_PACK: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_BYTE8) then begin
inc(primitiveKind, 4);
castByte8ToShort8(dst, dst, primitiveKind);
end;
case primitiveKind of
AVT_SHORT:
shortVectPack(dst, dst);
AVT_SHORT2:
short2VectPack(dst, dst);
AVT_SHORT4:
short4VectPack(dst, dst);
AVT_SHORT8:
short8VectPack(dst, dst);
AVT_INT:
intVectPack(dst, dst);
AVT_INT2:
int2VectPack(dst, dst);
AVT_INT4:
int4VectPack(dst, dst);
AVT_INT8:
int8VectPack(dst, dst);
AVT_LONG:
longVectPack(dst, dst);
AVT_LONG2:
long2VectPack(dst, dst);
AVT_LONG4:
long4VectPack(dst, dst);
AVT_LONG8:
long8VectPack(dst, dst);
else
goto label0;
end;
end;
OPER_VECT_UNPCKL: begin
case primitiveKind of
AVT_BYTE:
byteVectUnpckl(dst, dst);
AVT_BYTE2:
byte2VectUnpckl(dst, dst);
AVT_BYTE4:
byte4VectUnpckl(dst, dst);
AVT_BYTE8:
byte8VectUnpckl(dst, dst);
AVT_SHORT:
shortVectUnpckl(dst, dst);
AVT_SHORT2:
short2VectUnpckl(dst, dst);
AVT_SHORT4:
short4VectUnpckl(dst, dst);
AVT_SHORT8:
short8VectUnpckl(dst, dst);
AVT_INT:
intVectUnpckl(dst, dst);
AVT_INT2:
int2VectUnpckl(dst, dst);
AVT_INT4:
int4VectUnpckl(dst, dst);
AVT_INT8:
int8VectUnpckl(dst, dst);
else
goto label0;
end;
end;
OPER_VECT_UNPCKU: begin
case primitiveKind of
AVT_BYTE:
byteVectUnpcku(dst, dst);
AVT_BYTE2:
byte2VectUnpcku(dst, dst);
AVT_BYTE4:
byte4VectUnpcku(dst, dst);
AVT_BYTE8:
byte8VectUnpcku(dst, dst);
AVT_SHORT:
shortVectUnpcku(dst, dst);
AVT_SHORT2:
short2VectUnpcku(dst, dst);
AVT_SHORT4:
short4VectUnpcku(dst, dst);
AVT_SHORT8:
short8VectUnpcku(dst, dst);
AVT_INT:
intVectUnpcku(dst, dst);
AVT_INT2:
int2VectUnpcku(dst, dst);
AVT_INT4:
int4VectUnpcku(dst, dst);
AVT_INT8:
int8VectUnpcku(dst, dst);
else
goto label0;
end;
end;
OPER_VECT_PLUS: begin
case primitiveKind of
AVT_BYTE:
byteVectPlus(dst, dst);
AVT_BYTE2:
byte2VectPlus(dst, dst);
AVT_BYTE4:
byte4VectPlus(dst, dst);
AVT_BYTE8:
byte8VectPlus(dst, dst);
AVT_SHORT:
shortVectPlus(dst, dst);
AVT_SHORT2:
short2VectPlus(dst, dst);
AVT_SHORT4:
short4VectPlus(dst, dst);
AVT_SHORT8:
short8VectPlus(dst, dst);
AVT_INT:
intVectPlus(dst, dst);
AVT_INT2:
int2VectPlus(dst, dst);
AVT_INT4:
int4VectPlus(dst, dst);
AVT_INT8:
int8VectPlus(dst, dst);
AVT_LONG:
longVectPlus(dst, dst);
AVT_LONG2:
long2VectPlus(dst, dst);
AVT_LONG4:
long4VectPlus(dst, dst);
AVT_LONG8:
long8VectPlus(dst, dst);
AVT_FLOAT:
floatVectPlus(dst, dst);
AVT_FLOAT2:
float2VectPlus(dst, dst);
AVT_FLOAT4:
float4VectPlus(dst, dst);
AVT_FLOAT8:
float8VectPlus(dst, dst);
AVT_DOUBLE:
doubleVectPlus(dst, dst);
AVT_DOUBLE2:
double2VectPlus(dst, dst);
AVT_DOUBLE4:
double4VectPlus(dst, dst);
AVT_DOUBLE8:
double8VectPlus(dst, dst);
else
goto label0;
end;
end;
OPER_VECT_MINUS: begin
case primitiveKind of
AVT_BYTE:
byteVectMinus(dst, dst);
AVT_BYTE2:
byte2VectMinus(dst, dst);
AVT_BYTE4:
byte4VectMinus(dst, dst);
AVT_BYTE8:
byte8VectMinus(dst, dst);
AVT_SHORT:
shortVectMinus(dst, dst);
AVT_SHORT2:
short2VectMinus(dst, dst);
AVT_SHORT4:
short4VectMinus(dst, dst);
AVT_SHORT8:
short8VectMinus(dst, dst);
AVT_INT:
intVectMinus(dst, dst);
AVT_INT2:
int2VectMinus(dst, dst);
AVT_INT4:
int4VectMinus(dst, dst);
AVT_INT8:
int8VectMinus(dst, dst);
AVT_LONG:
longVectMinus(dst, dst);
AVT_LONG2:
long2VectMinus(dst, dst);
AVT_LONG4:
long4VectMinus(dst, dst);
AVT_LONG8:
long8VectMinus(dst, dst);
AVT_FLOAT:
floatVectMinus(dst, dst);
AVT_FLOAT2:
float2VectMinus(dst, dst);
AVT_FLOAT4:
float4VectMinus(dst, dst);
AVT_FLOAT8:
float8VectMinus(dst, dst);
AVT_DOUBLE:
doubleVectMinus(dst, dst);
AVT_DOUBLE2:
double2VectMinus(dst, dst);
AVT_DOUBLE4:
double4VectMinus(dst, dst);
AVT_DOUBLE8:
double8VectMinus(dst, dst);
else
goto label0;
end;
end;
OPER_TYPE_CAST: begin
typeCastRef := item.typeCast;
if typeCastRef.isBoolean() and typeOperandRef.isBoolean() then begin
continue;
end;
if typeCastRef.isNumeric() and typeOperandRef.isNumeric() then begin
if typeOperandRef <> typeCastRef then begin
cast(dst, dst, typeCastRef as AVTTypePrimitive);
expressionNode.dataType := typeCastRef;
end;
continue;
end;
raise AVTCompilerException.create('Can not cast from ' + typeOperandRef.fullName + ' to ' + typeCastRef.fullName, source, operatorPos);
end
else
raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, operatorPos);
end;
expressionNode.dataType := dst.valueType;
continue;
end;
if primitiveKind = AVT_CHAR then begin
primitiveKind := AVT_INT;
typeOperandRef := getPrimitiveType(AVT_INT);
end;
case operatorKind of
OPER_BOOL_NOT: begin
if primitiveKind = AVT_BOOLEAN then begin
typeReturnRef := typeOperandRef;
end else begin
goto label0;
end;
end;
OPER_BIT_NOT: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := typeOperandRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_PLUS: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
if (primitiveKind <> AVT_BYTE) and (primitiveKind <> AVT_SHORT) then begin
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeReturnRef, OPER_TYPE_CAST, typeReturnRef, typeOperandRef);
code.moveNode(expressionNode, currentNode, 0);
expressionNode := currentNode;
end;
continue;
end;
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
continue;
end;
goto label0;
end;
OPER_SCAL_MINUS: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeOperandRef;
end else begin
goto label0;
end;
end;
OPER_VECT_PACK: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_BYTE8) then begin
inc(primitiveKind, 4);
typeReturnRef := getPrimitiveType(primitiveKind);
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeReturnRef, OPER_TYPE_CAST, typeReturnRef, typeOperandRef);
code.moveNode(expressionNode, currentNode, 0);
expressionNode := currentNode;
typeOperandRef := typeReturnRef;
end;
if (primitiveKind >= AVT_SHORT) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := getPrimitiveType(primitiveKind - 4);
end else begin
goto label0;
end;
end;
OPER_VECT_UNPCKL, OPER_VECT_UNPCKU: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_INT8) then begin
typeReturnRef := getPrimitiveType(primitiveKind + 4);
end else begin
goto label0;
end;
end;
OPER_VECT_PLUS: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
continue;
end;
goto label0;
end;
OPER_VECT_MINUS: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := typeOperandRef;
end else begin
goto label0;
end;
end;
OPER_TYPE_CAST: begin
typeCastRef := item.typeCast;
if typeOperandRef.isBoolean() and typeCastRef.isBoolean() then begin
continue;
end;
if typeOperandRef.isNumeric() and typeCastRef.isNumeric() then begin
if typeOperandRef = typeCastRef then begin
expressionNode.dataType := typeCastRef;
end else begin
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeCastRef, OPER_TYPE_CAST, typeCastRef, typeOperandRef);
code.moveNode(expressionNode, currentNode, 0);
expressionNode := currentNode;
end;
continue;
end;
raise AVTCompilerException.create('Can not cast from ' + typeOperandRef.fullName + ' to ' + typeCastRef.fullName, source, operatorPos);
end
else { OPER_INC_PRED, OPER_DEC_PRED }
typeVoidRef := getPrimitiveType(AVT_VOID);
lineIndex := expressionNode.lineIndex;
case instruction of
LOAD_VARIABLE: begin
typeOperandRef := (expressionNode.operand1 as AVTVariable).valueType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
if operatorKind = OPER_INC_PRED then begin
expressionNode.instruction := OPER_INC_PRED;
end else begin
expressionNode.instruction := OPER_DEC_PRED;
end;
end;
LOAD_STATIC: begin
foundField := expressionNode.operand1 as AVTField;
if foundField.isFinal() then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
end;
typeOperandRef := foundField.valueType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
code.insertNode(currentNode).setData(lineIndex, typeOperandRef, LOAD_STATIC, foundField);
code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1);
expressionNode.instruction := STORE_STATIC;
end;
GET_FIELD: begin
foundField := expressionNode.operand1 as AVTField;
if foundField.isFinal() then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
end;
typeOperandRef := foundField.valueType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, GET_FIELD, foundField);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X1);
expressionNode.instruction := SET_FIELD;
end;
GET_PROPERTY: begin
foundProperty := expressionNode.operand1 as AVTProperty;
if foundProperty.writeSynthetic = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, pos);
end;
typeOperandRef := foundProperty.valueType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, GET_PROPERTY, foundProperty);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X1);
expressionNode.instruction := SET_PROPERTY;
end;
GET_ARRAY_ELEMENT: begin
typeOperandRef := expressionNode.operand1 as AVTType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, GET_ARRAY_ELEMENT, typeOperandRef);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X2);
expressionNode.instruction := SET_ARRAY_ELEMENT;
end;
INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
operand := expressionNode.operand1;
if (operand is AVTOperator) and (AVTOperator(operand).operatorKind = GET_ARRAY_ELEMENT) then begin
typeOperandRef := AVTMethod(operand).returnType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
typeDereferenceRef := expressionNode[0].dataType as AVTTypeStructured;
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(AVTMethod(operand).getArgumentAt(0).valueType, false));
argumentTypes.append(ValueOfObject.create(typeOperandRef, false));
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, operatorPos);
if (foundMethod = nil) or not foundMethod.isIdentityArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, operatorPos);
end;
finally
argumentTypes.free();
end;
if not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator []=' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, instruction, operand);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP2);
code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X2);
if (instruction <> INVOKE_SPECIAL) or foundMethod.isAbstract() then begin
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
end;
expressionNode.setData(lineIndex, typeOperandRef, instruction, foundMethod);
end else begin
foundProperty := (operand as AVTMethod).linkedProperty;
if (foundProperty = nil) or (foundProperty.readSynthetic <> operand) then begin
raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, operatorPos);
end;
typeOperandRef := foundProperty.valueType;
if not typeOperandRef.isNumeric() then begin
if operatorKind = OPER_INC_PRED then begin
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end else begin
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
foundMethod := foundProperty.writeSynthetic;
if foundMethod = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
end;
currentNode := insertIncrementCode(expressionNode, code, typeOperandRef as AVTTypePrimitive, operatorKind = OPER_INC_PRED, lineIndex);
currentNode := code.insertNode(currentNode, 0, lineIndex, typeOperandRef, instruction, operand);
code.appendNode(currentNode).setData(lineIndex, typeVoidRef, DUP1);
code.appendNode(expressionNode).setData(lineIndex, typeVoidRef, DUP1X1);
expressionNode.operand1 := foundMethod;
end;
end
else
raise AVTCompilerException.create('The operator ++/-- applicable only to variables, properties and array elements', source, operatorPos);
end;
continue;
end;
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeReturnRef, operatorKind, typeOperandRef);
code.moveNode(expressionNode, currentNode, 0);
expressionNode := currentNode;
continue;
end else
if typeOperandRef is AVTTypeStructured then begin
typeDereferenceRef := AVTTypeStructured(typeOperandRef);
case operatorKind of
OPER_BIT_NOT, OPER_SCAL_PLUS, OPER_SCAL_MINUS, OPER_VECT_PACK, OPER_VECT_UNPCKL, OPER_VECT_UNPCKU, OPER_VECT_PLUS, OPER_VECT_MINUS: begin
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(operatorKind), nil, typeRef, operatorPos);
if (foundMethod <> nil) and foundMethod.isIdentityArgumentTypes(nil) then begin
if not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), foundMethod.returnType, instruction, foundMethod);
code.moveNode(expressionNode, currentNode, 0);
expressionNode := currentNode;
continue;
end;
end;
OPER_TYPE_CAST: begin
typeCastRef := item.typeCast;
if typeCastRef is AVTTypeStructured then begin
if typeCastRef is AVTTypeArray then begin
AVTTypeArray(typeCastRef).makeCompilable();
end;
if typeCastRef = typeOperandRef then begin
continue;
end;
if typeCastRef.isAssignableFrom(typeOperandRef) then begin
expressionNode.dataType := typeCastRef;
continue;
end;
if not typeOperandRef.isFinal() and (typeCastRef.isService() or typeOperandRef.isAssignableFrom(typeCastRef)) then begin
currentNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), typeCastRef, OPER_TYPE_CAST, typeCastRef, typeOperandRef);
code.moveNode(expressionNode, currentNode, 0);
expressionNode := currentNode;
continue;
end;
end;
raise AVTCompilerException.create('Can not cast from ' + typeOperandRef.fullName + ' to ' + typeCastRef.fullName, source, operatorPos);
end;
end;
end;
label0:
case operatorKind of
OPER_SCAL_PLUS:
raise AVTCompilerException.create('The operator + is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
OPER_SCAL_MINUS:
raise AVTCompilerException.create('The operator - is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
OPER_INC_PRED:
raise AVTCompilerException.create('The operator ++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
OPER_DEC_PRED:
raise AVTCompilerException.create('The operator -- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
OPER_VECT_PLUS:
raise AVTCompilerException.create('The operator ++++ is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
OPER_VECT_MINUS:
raise AVTCompilerException.create('The operator ---- is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
else
raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument type ' + itemToString(typeOperandRef), source, operatorPos);
end;
end;
end;
finally
stack.free();
end;
result := pos;
end;
function AVTCodeBuilder.parseMultiplicative(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeReturnRef: AVTType;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parsePrefix(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
repeat
operatorKind := source.getLexemeType(pos);
case operatorKind of
OPER_SCAL_MUL, OPER_SCAL_DIV, OPER_SCAL_DIVU, OPER_SCAL_REM, OPER_SCAL_REMU, OPER_VECT_MUL, OPER_VECT_MULS, OPER_VECT_MULU, OPER_VECT_DIV: begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parsePrefix(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
end
else
break;
end;
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case operatorKind of
OPER_SCAL_MUL: begin
case primitiveKind of
AVT_BYTE:
byteScalMul(dst, op0, op1);
AVT_BYTE2:
byte2ScalMul(dst, op0, op1);
AVT_BYTE4:
byte4ScalMul(dst, op0, op1);
AVT_BYTE8:
byte8ScalMul(dst, op0, op1);
AVT_SHORT:
shortScalMul(dst, op0, op1);
AVT_SHORT2:
short2ScalMul(dst, op0, op1);
AVT_SHORT4:
short4ScalMul(dst, op0, op1);
AVT_SHORT8:
short8ScalMul(dst, op0, op1);
AVT_INT:
intScalMul(dst, op0, op1);
AVT_INT2:
int2ScalMul(dst, op0, op1);
AVT_INT4:
int4ScalMul(dst, op0, op1);
AVT_INT8:
int8ScalMul(dst, op0, op1);
AVT_LONG:
longScalMul(dst, op0, op1);
AVT_LONG2:
long2ScalMul(dst, op0, op1);
AVT_LONG4:
long4ScalMul(dst, op0, op1);
AVT_LONG8:
long8ScalMul(dst, op0, op1);
AVT_FLOAT:
floatScalMul(dst, op0, op1);
AVT_FLOAT2:
float2ScalMul(dst, op0, op1);
AVT_FLOAT4:
float4ScalMul(dst, op0, op1);
AVT_FLOAT8:
float8ScalMul(dst, op0, op1);
AVT_DOUBLE:
doubleScalMul(dst, op0, op1);
AVT_DOUBLE2:
double2ScalMul(dst, op0, op1);
AVT_DOUBLE4:
double4ScalMul(dst, op0, op1);
AVT_DOUBLE8:
double8ScalMul(dst, op0, op1);
AVT_REAL:
realScalMul(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_DIV: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
dst.free();
raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
end;
case primitiveKind of
AVT_BYTE:
byteScalDiv(dst, op0, op1);
AVT_SHORT:
shortScalDiv(dst, op0, op1);
AVT_INT:
intScalDiv(dst, op0, op1);
AVT_LONG:
longScalDiv(dst, op0, op1);
AVT_FLOAT:
floatScalDiv(dst, op0, op1);
AVT_FLOAT2:
float2ScalDiv(dst, op0, op1);
AVT_FLOAT4:
float4ScalDiv(dst, op0, op1);
AVT_FLOAT8:
float8ScalDiv(dst, op0, op1);
AVT_DOUBLE:
doubleScalDiv(dst, op0, op1);
AVT_DOUBLE2:
double2ScalDiv(dst, op0, op1);
AVT_DOUBLE4:
double4ScalDiv(dst, op0, op1);
AVT_DOUBLE8:
double8ScalDiv(dst, op0, op1);
AVT_REAL:
realScalDiv(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_DIVU: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
dst.free();
raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
end;
case primitiveKind of
AVT_BYTE:
byteScalDivu(dst, op0, op1);
AVT_SHORT:
shortScalDivu(dst, op0, op1);
AVT_INT:
intScalDivu(dst, op0, op1);
AVT_LONG:
longScalDivu(dst, op0, op1);
AVT_FLOAT:
floatScalDivu(dst, op0, op1);
AVT_FLOAT2:
float2ScalDivu(dst, op0, op1);
AVT_FLOAT4:
float4ScalDivu(dst, op0, op1);
AVT_FLOAT8:
float8ScalDivu(dst, op0, op1);
AVT_DOUBLE:
doubleScalDivu(dst, op0, op1);
AVT_DOUBLE2:
double2ScalDivu(dst, op0, op1);
AVT_DOUBLE4:
double4ScalDivu(dst, op0, op1);
AVT_DOUBLE8:
double8ScalDivu(dst, op0, op1);
AVT_REAL:
realScalDivu(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_REM: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
dst.free();
raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
end;
case primitiveKind of
AVT_BYTE:
byteScalRem(dst, op0, op1);
AVT_SHORT:
shortScalRem(dst, op0, op1);
AVT_INT:
intScalRem(dst, op0, op1);
AVT_LONG:
longScalRem(dst, op0, op1);
AVT_FLOAT:
floatScalRem(dst, op0, op1);
AVT_DOUBLE:
doubleScalRem(dst, op0, op1);
AVT_REAL:
realScalRem(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_REMU: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) and op1.isDefaultValue() then begin
dst.free();
raise AVTCompilerException.create('Integer constant division by zero error', source, operatorPos);
end;
case primitiveKind of
AVT_BYTE:
byteScalRemu(dst, op0, op1);
AVT_SHORT:
shortScalRemu(dst, op0, op1);
AVT_INT:
intScalRemu(dst, op0, op1);
AVT_LONG:
longScalRemu(dst, op0, op1);
AVT_FLOAT:
floatScalRemu(dst, op0, op1);
AVT_DOUBLE:
doubleScalRemu(dst, op0, op1);
AVT_REAL:
realScalRemu(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_MUL: begin
case primitiveKind of
AVT_BYTE:
byteVectMul(dst, op0, op1);
AVT_BYTE2:
byte2VectMul(dst, op0, op1);
AVT_BYTE4:
byte4VectMul(dst, op0, op1);
AVT_BYTE8:
byte8VectMul(dst, op0, op1);
AVT_SHORT:
shortVectMul(dst, op0, op1);
AVT_SHORT2:
short2VectMul(dst, op0, op1);
AVT_SHORT4:
short4VectMul(dst, op0, op1);
AVT_SHORT8:
short8VectMul(dst, op0, op1);
AVT_INT:
intVectMul(dst, op0, op1);
AVT_INT2:
int2VectMul(dst, op0, op1);
AVT_INT4:
int4VectMul(dst, op0, op1);
AVT_INT8:
int8VectMul(dst, op0, op1);
AVT_LONG:
longVectMul(dst, op0, op1);
AVT_LONG2:
long2VectMul(dst, op0, op1);
AVT_LONG4:
long4VectMul(dst, op0, op1);
AVT_LONG8:
long8VectMul(dst, op0, op1);
AVT_FLOAT:
floatVectMul(dst, op0, op1);
AVT_FLOAT2:
float2VectMul(dst, op0, op1);
AVT_FLOAT4:
float4VectMul(dst, op0, op1);
AVT_FLOAT8:
float8VectMul(dst, op0, op1);
AVT_DOUBLE:
doubleVectMul(dst, op0, op1);
AVT_DOUBLE2:
double2VectMul(dst, op0, op1);
AVT_DOUBLE4:
double4VectMul(dst, op0, op1);
AVT_DOUBLE8:
double8VectMul(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_MULS: begin
case primitiveKind of
AVT_BYTE:
byteVectMuls(dst, op0, op1);
AVT_BYTE2:
byte2VectMuls(dst, op0, op1);
AVT_BYTE4:
byte4VectMuls(dst, op0, op1);
AVT_BYTE8:
byte8VectMuls(dst, op0, op1);
AVT_SHORT:
shortVectMuls(dst, op0, op1);
AVT_SHORT2:
short2VectMuls(dst, op0, op1);
AVT_SHORT4:
short4VectMuls(dst, op0, op1);
AVT_SHORT8:
short8VectMuls(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_MULU: begin
case primitiveKind of
AVT_BYTE:
byteVectMulu(dst, op0, op1);
AVT_BYTE2:
byte2VectMulu(dst, op0, op1);
AVT_BYTE4:
byte4VectMulu(dst, op0, op1);
AVT_BYTE8:
byte8VectMulu(dst, op0, op1);
AVT_SHORT:
shortVectMulu(dst, op0, op1);
AVT_SHORT2:
short2VectMulu(dst, op0, op1);
AVT_SHORT4:
short4VectMulu(dst, op0, op1);
AVT_SHORT8:
short8VectMulU(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_DIV: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_BYTE8) then begin
primitiveKind := AVT_FLOAT + (primitiveKind and 3);
castByte8ToFloat8(op0, op0, primitiveKind);
castByte8ToFloat8(op1, op1, primitiveKind);
end else
if (primitiveKind >= AVT_SHORT) and (primitiveKind <= AVT_SHORT8) then begin
primitiveKind := AVT_FLOAT + (primitiveKind and 3);
castShort8ToFloat8(op0, op0, primitiveKind);
castShort8ToFloat8(op1, op1, primitiveKind);
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_INT8) then begin
primitiveKind := AVT_DOUBLE + (primitiveKind and 3);
castInt8ToDouble8(op0, op0, primitiveKind);
castInt8ToDouble8(op1, op1, primitiveKind);
end;
case primitiveKind of
AVT_FLOAT:
floatVectDiv(dst, op0, op1);
AVT_FLOAT2:
float2VectDiv(dst, op0, op1);
AVT_FLOAT4:
float4VectDiv(dst, op0, op1);
AVT_FLOAT8:
float8VectDiv(dst, op0, op1);
AVT_DOUBLE:
doubleVectDiv(dst, op0, op1);
AVT_DOUBLE2:
double2VectDiv(dst, op0, op1);
AVT_DOUBLE4:
double4VectDiv(dst, op0, op1);
AVT_DOUBLE8:
double8VectDiv(dst, op0, op1);
else
goto label0;
end;
end;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
case operatorKind of
OPER_SCAL_MUL: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_DIV, OPER_SCAL_DIVU: begin
if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
typeReturnRef := getPrimitiveType(AVT_INT);
end else
if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_REM, OPER_SCAL_REMU: begin
if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
typeReturnRef := getPrimitiveType(AVT_INT);
end else
if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind = AVT_FLOAT) or (primitiveKind = AVT_DOUBLE) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_VECT_MUL: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_VECT_MULS, OPER_VECT_MULU: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_VECT_DIV: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
primitiveKind := AVT_FLOAT + (primitiveKind and 3);
typeCommonRef := getPrimitiveType(primitiveKind);
cast(operand0Node, code, typeCommonRef);
cast(operand1Node, code, typeCommonRef);
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_INT8) then begin
primitiveKind := AVT_DOUBLE + (primitiveKind and 3);
typeCommonRef := getPrimitiveType(primitiveKind);
cast(operand0Node, code, typeCommonRef);
cast(operand1Node, code, typeCommonRef);
end;
if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeReturnRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
until false;
result := pos;
end;
function AVTCodeBuilder.parseAdditive(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeReturnRef: AVTType;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
typeString: AVTTypeStructured;
begin
pos := parseMultiplicative(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
repeat
operatorKind := source.getLexemeType(pos);
case operatorKind of
OPER_SCAL_ADD, OPER_SCAL_SUB, OPER_VECT_ADD, OPER_VECT_ADDS, OPER_VECT_ADDU, OPER_VECT_SUB, OPER_VECT_SUBS, OPER_VECT_SUBU: begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseMultiplicative(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
end
else
break;
end;
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case operatorKind of
OPER_SCAL_ADD: begin
case primitiveKind of
AVT_BYTE:
byteScalAdd(dst, op0, op1);
AVT_BYTE2:
byte2ScalAdd(dst, op0, op1);
AVT_BYTE4:
byte4ScalAdd(dst, op0, op1);
AVT_BYTE8:
byte8ScalAdd(dst, op0, op1);
AVT_SHORT:
shortScalAdd(dst, op0, op1);
AVT_SHORT2:
short2ScalAdd(dst, op0, op1);
AVT_SHORT4:
short4ScalAdd(dst, op0, op1);
AVT_SHORT8:
short8ScalAdd(dst, op0, op1);
AVT_INT:
intScalAdd(dst, op0, op1);
AVT_INT2:
int2ScalAdd(dst, op0, op1);
AVT_INT4:
int4ScalAdd(dst, op0, op1);
AVT_INT8:
int8ScalAdd(dst, op0, op1);
AVT_LONG:
longScalAdd(dst, op0, op1);
AVT_LONG2:
long2ScalAdd(dst, op0, op1);
AVT_LONG4:
long4ScalAdd(dst, op0, op1);
AVT_LONG8:
long8ScalAdd(dst, op0, op1);
AVT_FLOAT:
floatScalAdd(dst, op0, op1);
AVT_FLOAT2:
float2ScalAdd(dst, op0, op1);
AVT_FLOAT4:
float4ScalAdd(dst, op0, op1);
AVT_FLOAT8:
float8ScalAdd(dst, op0, op1);
AVT_DOUBLE:
doubleScalAdd(dst, op0, op1);
AVT_DOUBLE2:
double2ScalAdd(dst, op0, op1);
AVT_DOUBLE4:
double4ScalAdd(dst, op0, op1);
AVT_DOUBLE8:
double8ScalAdd(dst, op0, op1);
AVT_REAL:
realScalAdd(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_SUB: begin
case primitiveKind of
AVT_BYTE:
byteScalSub(dst, op0, op1);
AVT_BYTE2:
byte2ScalSub(dst, op0, op1);
AVT_BYTE4:
byte4ScalSub(dst, op0, op1);
AVT_BYTE8:
byte8ScalSub(dst, op0, op1);
AVT_SHORT:
shortScalSub(dst, op0, op1);
AVT_SHORT2:
short2ScalSub(dst, op0, op1);
AVT_SHORT4:
short4ScalSub(dst, op0, op1);
AVT_SHORT8:
short8ScalSub(dst, op0, op1);
AVT_INT:
intScalSub(dst, op0, op1);
AVT_INT2:
int2ScalSub(dst, op0, op1);
AVT_INT4:
int4ScalSub(dst, op0, op1);
AVT_INT8:
int8ScalSub(dst, op0, op1);
AVT_LONG:
longScalSub(dst, op0, op1);
AVT_LONG2:
long2ScalSub(dst, op0, op1);
AVT_LONG4:
long4ScalSub(dst, op0, op1);
AVT_LONG8:
long8ScalSub(dst, op0, op1);
AVT_FLOAT:
floatScalSub(dst, op0, op1);
AVT_FLOAT2:
float2ScalSub(dst, op0, op1);
AVT_FLOAT4:
float4ScalSub(dst, op0, op1);
AVT_FLOAT8:
float8ScalSub(dst, op0, op1);
AVT_DOUBLE:
doubleScalSub(dst, op0, op1);
AVT_DOUBLE2:
double2ScalSub(dst, op0, op1);
AVT_DOUBLE4:
double4ScalSub(dst, op0, op1);
AVT_DOUBLE8:
double8ScalSub(dst, op0, op1);
AVT_REAL:
realScalSub(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_ADD: begin
case primitiveKind of
AVT_BYTE:
byteVectAdd(dst, op0, op1);
AVT_BYTE2:
byte2VectAdd(dst, op0, op1);
AVT_BYTE4:
byte4VectAdd(dst, op0, op1);
AVT_BYTE8:
byte8VectAdd(dst, op0, op1);
AVT_SHORT:
shortVectAdd(dst, op0, op1);
AVT_SHORT2:
short2VectAdd(dst, op0, op1);
AVT_SHORT4:
short4VectAdd(dst, op0, op1);
AVT_SHORT8:
short8VectAdd(dst, op0, op1);
AVT_INT:
intVectAdd(dst, op0, op1);
AVT_INT2:
int2VectAdd(dst, op0, op1);
AVT_INT4:
int4VectAdd(dst, op0, op1);
AVT_INT8:
int8VectAdd(dst, op0, op1);
AVT_LONG:
longVectAdd(dst, op0, op1);
AVT_LONG2:
long2VectAdd(dst, op0, op1);
AVT_LONG4:
long4VectAdd(dst, op0, op1);
AVT_LONG8:
long8VectAdd(dst, op0, op1);
AVT_FLOAT:
floatVectAdd(dst, op0, op1);
AVT_FLOAT2:
float2VectAdd(dst, op0, op1);
AVT_FLOAT4:
float4VectAdd(dst, op0, op1);
AVT_FLOAT8:
float8VectAdd(dst, op0, op1);
AVT_DOUBLE:
doubleVectAdd(dst, op0, op1);
AVT_DOUBLE2:
double2VectAdd(dst, op0, op1);
AVT_DOUBLE4:
double4VectAdd(dst, op0, op1);
AVT_DOUBLE8:
double8VectAdd(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_ADDS: begin
case primitiveKind of
AVT_BYTE:
byteVectAdds(dst, op0, op1);
AVT_BYTE2:
byte2VectAdds(dst, op0, op1);
AVT_BYTE4:
byte4VectAdds(dst, op0, op1);
AVT_BYTE8:
byte8VectAdds(dst, op0, op1);
AVT_SHORT:
shortVectAdds(dst, op0, op1);
AVT_SHORT2:
short2VectAdds(dst, op0, op1);
AVT_SHORT4:
short4VectAdds(dst, op0, op1);
AVT_SHORT8:
short8VectAdds(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_ADDU: begin
case primitiveKind of
AVT_BYTE:
byteVectAddu(dst, op0, op1);
AVT_BYTE2:
byte2VectAddu(dst, op0, op1);
AVT_BYTE4:
byte4VectAddu(dst, op0, op1);
AVT_BYTE8:
byte8VectAddu(dst, op0, op1);
AVT_SHORT:
shortVectAddu(dst, op0, op1);
AVT_SHORT2:
short2VectAddu(dst, op0, op1);
AVT_SHORT4:
short4VectAddu(dst, op0, op1);
AVT_SHORT8:
short8VectAddu(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_SUB: begin
case primitiveKind of
AVT_BYTE:
byteVectSub(dst, op0, op1);
AVT_BYTE2:
byte2VectSub(dst, op0, op1);
AVT_BYTE4:
byte4VectSub(dst, op0, op1);
AVT_BYTE8:
byte8VectSub(dst, op0, op1);
AVT_SHORT:
shortVectSub(dst, op0, op1);
AVT_SHORT2:
short2VectSub(dst, op0, op1);
AVT_SHORT4:
short4VectSub(dst, op0, op1);
AVT_SHORT8:
short8VectSub(dst, op0, op1);
AVT_INT:
intVectSub(dst, op0, op1);
AVT_INT2:
int2VectSub(dst, op0, op1);
AVT_INT4:
int4VectSub(dst, op0, op1);
AVT_INT8:
int8VectSub(dst, op0, op1);
AVT_LONG:
longVectSub(dst, op0, op1);
AVT_LONG2:
long2VectSub(dst, op0, op1);
AVT_LONG4:
long4VectSub(dst, op0, op1);
AVT_LONG8:
long8VectSub(dst, op0, op1);
AVT_FLOAT:
floatVectSub(dst, op0, op1);
AVT_FLOAT2:
float2VectSub(dst, op0, op1);
AVT_FLOAT4:
float4VectSub(dst, op0, op1);
AVT_FLOAT8:
float8VectSub(dst, op0, op1);
AVT_DOUBLE:
doubleVectSub(dst, op0, op1);
AVT_DOUBLE2:
double2VectSub(dst, op0, op1);
AVT_DOUBLE4:
double4VectSub(dst, op0, op1);
AVT_DOUBLE8:
double8VectSub(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_SUBS: begin
case primitiveKind of
AVT_BYTE:
byteVectSubs(dst, op0, op1);
AVT_BYTE2:
byte2VectSubs(dst, op0, op1);
AVT_BYTE4:
byte4VectSubs(dst, op0, op1);
AVT_BYTE8:
byte8VectSubs(dst, op0, op1);
AVT_SHORT:
shortVectSubs(dst, op0, op1);
AVT_SHORT2:
short2VectSubs(dst, op0, op1);
AVT_SHORT4:
short4VectSubs(dst, op0, op1);
AVT_SHORT8:
short8VectSubs(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_SUBU: begin
case primitiveKind of
AVT_BYTE:
byteVectSubu(dst, op0, op1);
AVT_BYTE2:
byte2VectSubu(dst, op0, op1);
AVT_BYTE4:
byte4VectSubu(dst, op0, op1);
AVT_BYTE8:
byte8VectSubu(dst, op0, op1);
AVT_SHORT:
shortVectSubu(dst, op0, op1);
AVT_SHORT2:
short2VectSubu(dst, op0, op1);
AVT_SHORT4:
short4VectSubu(dst, op0, op1);
AVT_SHORT8:
short8VectSubu(dst, op0, op1);
else
goto label0;
end;
end;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
case operatorKind of
OPER_SCAL_ADD, OPER_SCAL_SUB: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_VECT_ADD, OPER_VECT_SUB: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
OPER_VECT_ADDS, OPER_VECT_ADDU, OPER_VECT_SUBS, OPER_VECT_SUBU: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := typeCommonRef;
end else begin
goto label0;
end;
end;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeReturnRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
typeString := getStringType();
if (operatorKind = OPER_SCAL_ADD) and (typeOperand0Ref = typeString) and (operand0Node.instruction = LOAD_CONST) and (typeOperand1Ref = typeString) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
dst := AVTConstant.create(typeString);
dst.value.asString := op0.value.asString + op1.value.asString;
expressionNode.setData(expressionNode.lineIndex, typeString, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
until false;
result := pos;
end;
function AVTCodeBuilder.parseShift(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isChar: boolean;
isRight: boolean;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeReturnRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseAdditive(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
repeat
operatorKind := source.getLexemeType(pos);
case operatorKind of
OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR: begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseAdditive(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
end
else
break;
end;
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
if (typeOperand0Ref is AVTTypePrimitive) and (typeOperand1Ref is AVTTypePrimitive) then begin
primitiveKind := AVTTypePrimitive(typeOperand0Ref).primitiveKind;
if primitiveKind = AVT_CHAR then begin
isChar := true;
primitiveKind := AVT_INT;
typeOperand0Ref := getPrimitiveType(AVT_INT);
end else begin
isChar := false;
end;
if ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) or not typeOperand1Ref.isInt() then begin
goto label0;
end;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
if isChar then begin
op0.value.asInt := int(op0.value.asChar);
end;
dst := AVTConstant.create();
case operatorKind of
OPER_SCAL_SAR: begin
case primitiveKind of
AVT_BYTE:
byteScalSar(dst, op0, op1);
AVT_BYTE2:
byte2ScalSar(dst, op0, op1);
AVT_BYTE4:
byte4ScalSar(dst, op0, op1);
AVT_BYTE8:
byte8ScalSar(dst, op0, op1);
AVT_SHORT:
shortScalSar(dst, op0, op1);
AVT_SHORT2:
short2ScalSar(dst, op0, op1);
AVT_SHORT4:
short4ScalSar(dst, op0, op1);
AVT_SHORT8:
short8ScalSar(dst, op0, op1);
AVT_INT:
intScalSar(dst, op0, op1);
AVT_INT2:
int2ScalSar(dst, op0, op1);
AVT_INT4:
int4ScalSar(dst, op0, op1);
AVT_INT8:
int8ScalSar(dst, op0, op1);
AVT_LONG:
longScalSar(dst, op0, op1);
AVT_LONG2:
long2ScalSar(dst, op0, op1);
AVT_LONG4:
long4ScalSar(dst, op0, op1);
AVT_LONG8:
long8ScalSar(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_SAL: begin
case primitiveKind of
AVT_BYTE:
byteScalSal(dst, op0, op1);
AVT_BYTE2:
byte2ScalSal(dst, op0, op1);
AVT_BYTE4:
byte4ScalSal(dst, op0, op1);
AVT_BYTE8:
byte8ScalSal(dst, op0, op1);
AVT_SHORT:
shortScalSal(dst, op0, op1);
AVT_SHORT2:
short2ScalSal(dst, op0, op1);
AVT_SHORT4:
short4ScalSal(dst, op0, op1);
AVT_SHORT8:
short8ScalSal(dst, op0, op1);
AVT_INT:
intScalSal(dst, op0, op1);
AVT_INT2:
int2ScalSal(dst, op0, op1);
AVT_INT4:
int4ScalSal(dst, op0, op1);
AVT_INT8:
int8ScalSal(dst, op0, op1);
AVT_LONG:
longScalSal(dst, op0, op1);
AVT_LONG2:
long2ScalSal(dst, op0, op1);
AVT_LONG4:
long4ScalSal(dst, op0, op1);
AVT_LONG8:
long8ScalSal(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_SHR: begin
case primitiveKind of
AVT_BYTE:
byteScalShr(dst, op0, op1);
AVT_BYTE2:
byte2ScalShr(dst, op0, op1);
AVT_BYTE4:
byte4ScalShr(dst, op0, op1);
AVT_BYTE8:
byte8ScalShr(dst, op0, op1);
AVT_SHORT:
shortScalShr(dst, op0, op1);
AVT_SHORT2:
short2ScalShr(dst, op0, op1);
AVT_SHORT4:
short4ScalShr(dst, op0, op1);
AVT_SHORT8:
short8ScalShr(dst, op0, op1);
AVT_INT:
intScalShr(dst, op0, op1);
AVT_INT2:
int2ScalShr(dst, op0, op1);
AVT_INT4:
int4ScalShr(dst, op0, op1);
AVT_INT8:
int8ScalShr(dst, op0, op1);
AVT_LONG:
longScalShr(dst, op0, op1);
AVT_LONG2:
long2ScalShr(dst, op0, op1);
AVT_LONG4:
long4ScalShr(dst, op0, op1);
AVT_LONG8:
long8ScalShr(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_SAR: begin
case primitiveKind of
AVT_BYTE:
byteVectSar(dst, op0, op1);
AVT_BYTE2:
byte2VectSar(dst, op0, op1);
AVT_BYTE4:
byte4VectSar(dst, op0, op1);
AVT_BYTE8:
byte8VectSar(dst, op0, op1);
AVT_SHORT:
shortVectSar(dst, op0, op1);
AVT_SHORT2:
short2VectSar(dst, op0, op1);
AVT_SHORT4:
short4VectSar(dst, op0, op1);
AVT_SHORT8:
short8VectSar(dst, op0, op1);
AVT_INT:
intVectSar(dst, op0, op1);
AVT_INT2:
int2VectSar(dst, op0, op1);
AVT_INT4:
int4VectSar(dst, op0, op1);
AVT_INT8:
int8VectSar(dst, op0, op1);
AVT_LONG:
longVectSar(dst, op0, op1);
AVT_LONG2:
long2VectSar(dst, op0, op1);
AVT_LONG4:
long4VectSar(dst, op0, op1);
AVT_LONG8:
long8VectSar(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_SAL: begin
case primitiveKind of
AVT_BYTE:
byteVectSal(dst, op0, op1);
AVT_BYTE2:
byte2VectSal(dst, op0, op1);
AVT_BYTE4:
byte4VectSal(dst, op0, op1);
AVT_BYTE8:
byte8VectSal(dst, op0, op1);
AVT_SHORT:
shortVectSal(dst, op0, op1);
AVT_SHORT2:
short2VectSal(dst, op0, op1);
AVT_SHORT4:
short4VectSal(dst, op0, op1);
AVT_SHORT8:
short8VectSal(dst, op0, op1);
AVT_INT:
intVectSal(dst, op0, op1);
AVT_INT2:
int2VectSal(dst, op0, op1);
AVT_INT4:
int4VectSal(dst, op0, op1);
AVT_INT8:
int8VectSal(dst, op0, op1);
AVT_LONG:
longVectSal(dst, op0, op1);
AVT_LONG2:
long2VectSal(dst, op0, op1);
AVT_LONG4:
long4VectSal(dst, op0, op1);
AVT_LONG8:
long8VectSal(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_SHR: begin
case primitiveKind of
AVT_BYTE:
byteVectShr(dst, op0, op1);
AVT_BYTE2:
byte2VectShr(dst, op0, op1);
AVT_BYTE4:
byte4VectShr(dst, op0, op1);
AVT_BYTE8:
byte8VectShr(dst, op0, op1);
AVT_SHORT:
shortVectShr(dst, op0, op1);
AVT_SHORT2:
short2VectShr(dst, op0, op1);
AVT_SHORT4:
short4VectShr(dst, op0, op1);
AVT_SHORT8:
short8VectShr(dst, op0, op1);
AVT_INT:
intVectShr(dst, op0, op1);
AVT_INT2:
int2VectShr(dst, op0, op1);
AVT_INT4:
int4VectShr(dst, op0, op1);
AVT_INT8:
int8VectShr(dst, op0, op1);
AVT_LONG:
longVectShr(dst, op0, op1);
AVT_LONG2:
long2VectShr(dst, op0, op1);
AVT_LONG4:
long4VectShr(dst, op0, op1);
AVT_LONG8:
long8VectShr(dst, op0, op1);
else
goto label0;
end;
end;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
case operatorKind of
OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR: begin
if primitiveKind < AVT_INT then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
end else begin
typeReturnRef := typeOperand0Ref;
end;
end;
OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR: begin
typeReturnRef := typeOperand0Ref;
end;
end;
expressionNode.dataType := typeReturnRef;
expressionNode.operand1 := typeOperand0Ref;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
until false;
result := pos;
end;
function AVTCodeBuilder.parseRelational(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeReturnRef: AVTType;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseShift(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
repeat
operatorKind := source.getLexemeType(pos);
case operatorKind of
AVT_INSTANCEOF: begin
operatorPos := pos;
typeReturnRef := parseType(parentNode, methodRef, typeRef, source, pos + 1);
if not(typeReturnRef is AVTTypeStructured) then begin
raise AVTCompilerException.create('Reference type expected', source, operatorPos + 1);
end;
operand0Node := parentNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
if (typeOperand0Ref <> nil) and not(typeOperand0Ref is AVTTypeStructured) then begin
raise AVTCompilerException.create('The operator instanceof is undefined for the argument type ' + itemToString(typeOperand0Ref), source, operatorPos);
end;
if typeOperand0Ref is AVTTypeArray then begin
AVTTypeArray(typeOperand0Ref).makeCompilable();
end;
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(operatorPos), getPrimitiveType(AVT_BOOLEAN), AVT_INSTANCEOF, typeReturnRef);
code.moveNode(operand0Node, expressionNode, 0);
pos := source.position;
continue;
end;
OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE, OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE: begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseShift(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
end
else
break;
end;
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case operatorKind of
OPER_SCAL_G: begin
case primitiveKind of
AVT_BYTE:
byteScalG(dst, op0, op1);
AVT_SHORT:
shortScalG(dst, op0, op1);
AVT_INT:
intScalG(dst, op0, op1);
AVT_LONG:
longScalG(dst, op0, op1);
AVT_FLOAT:
floatScalG(dst, op0, op1);
AVT_DOUBLE:
doubleScalG(dst, op0, op1);
AVT_REAL:
realScalG(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_GE: begin
case primitiveKind of
AVT_BYTE:
byteScalGE(dst, op0, op1);
AVT_SHORT:
shortScalGE(dst, op0, op1);
AVT_INT:
intScalGE(dst, op0, op1);
AVT_LONG:
longScalGE(dst, op0, op1);
AVT_FLOAT:
floatScalGE(dst, op0, op1);
AVT_DOUBLE:
doubleScalGE(dst, op0, op1);
AVT_REAL:
realScalGE(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_L: begin
case primitiveKind of
AVT_BYTE:
byteScalL(dst, op0, op1);
AVT_SHORT:
shortScalL(dst, op0, op1);
AVT_INT:
intScalL(dst, op0, op1);
AVT_LONG:
longScalL(dst, op0, op1);
AVT_FLOAT:
floatScalL(dst, op0, op1);
AVT_DOUBLE:
doubleScalL(dst, op0, op1);
AVT_REAL:
realScalL(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_LE: begin
case primitiveKind of
AVT_BYTE:
byteScalLE(dst, op0, op1);
AVT_SHORT:
shortScalLE(dst, op0, op1);
AVT_INT:
intScalLE(dst, op0, op1);
AVT_LONG:
longScalLE(dst, op0, op1);
AVT_FLOAT:
floatScalLE(dst, op0, op1);
AVT_DOUBLE:
doubleScalLE(dst, op0, op1);
AVT_REAL:
realScalLE(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_G: begin
case primitiveKind of
AVT_BYTE:
byteVectG(dst, op0, op1);
AVT_BYTE2:
byte2VectG(dst, op0, op1);
AVT_BYTE4:
byte4VectG(dst, op0, op1);
AVT_BYTE8:
byte8VectG(dst, op0, op1);
AVT_SHORT:
shortVectG(dst, op0, op1);
AVT_SHORT2:
short2VectG(dst, op0, op1);
AVT_SHORT4:
short4VectG(dst, op0, op1);
AVT_SHORT8:
short8VectG(dst, op0, op1);
AVT_INT:
intVectG(dst, op0, op1);
AVT_INT2:
int2VectG(dst, op0, op1);
AVT_INT4:
int4VectG(dst, op0, op1);
AVT_INT8:
int8VectG(dst, op0, op1);
AVT_LONG:
longVectG(dst, op0, op1);
AVT_LONG2:
long2VectG(dst, op0, op1);
AVT_LONG4:
long4VectG(dst, op0, op1);
AVT_LONG8:
long8VectG(dst, op0, op1);
AVT_FLOAT:
floatVectG(dst, op0, op1);
AVT_FLOAT2:
float2VectG(dst, op0, op1);
AVT_FLOAT4:
float4VectG(dst, op0, op1);
AVT_FLOAT8:
float8VectG(dst, op0, op1);
AVT_DOUBLE:
doubleVectG(dst, op0, op1);
AVT_DOUBLE2:
double2VectG(dst, op0, op1);
AVT_DOUBLE4:
double4VectG(dst, op0, op1);
AVT_DOUBLE8:
double8VectG(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_GE: begin
case primitiveKind of
AVT_BYTE:
byteVectGE(dst, op0, op1);
AVT_BYTE2:
byte2VectGE(dst, op0, op1);
AVT_BYTE4:
byte4VectGE(dst, op0, op1);
AVT_BYTE8:
byte8VectGE(dst, op0, op1);
AVT_SHORT:
shortVectGE(dst, op0, op1);
AVT_SHORT2:
short2VectGE(dst, op0, op1);
AVT_SHORT4:
short4VectGE(dst, op0, op1);
AVT_SHORT8:
short8VectGE(dst, op0, op1);
AVT_INT:
intVectGE(dst, op0, op1);
AVT_INT2:
int2VectGE(dst, op0, op1);
AVT_INT4:
int4VectGE(dst, op0, op1);
AVT_INT8:
int8VectGE(dst, op0, op1);
AVT_LONG:
longVectGE(dst, op0, op1);
AVT_LONG2:
long2VectGE(dst, op0, op1);
AVT_LONG4:
long4VectGE(dst, op0, op1);
AVT_LONG8:
long8VectGE(dst, op0, op1);
AVT_FLOAT:
floatVectGE(dst, op0, op1);
AVT_FLOAT2:
float2VectGE(dst, op0, op1);
AVT_FLOAT4:
float4VectGE(dst, op0, op1);
AVT_FLOAT8:
float8VectGE(dst, op0, op1);
AVT_DOUBLE:
doubleVectGE(dst, op0, op1);
AVT_DOUBLE2:
double2VectGE(dst, op0, op1);
AVT_DOUBLE4:
double4VectGE(dst, op0, op1);
AVT_DOUBLE8:
double8VectGE(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_L: begin
case primitiveKind of
AVT_BYTE:
byteVectL(dst, op0, op1);
AVT_BYTE2:
byte2VectL(dst, op0, op1);
AVT_BYTE4:
byte4VectL(dst, op0, op1);
AVT_BYTE8:
byte8VectL(dst, op0, op1);
AVT_SHORT:
shortVectL(dst, op0, op1);
AVT_SHORT2:
short2VectL(dst, op0, op1);
AVT_SHORT4:
short4VectL(dst, op0, op1);
AVT_SHORT8:
short8VectL(dst, op0, op1);
AVT_INT:
intVectL(dst, op0, op1);
AVT_INT2:
int2VectL(dst, op0, op1);
AVT_INT4:
int4VectL(dst, op0, op1);
AVT_INT8:
int8VectL(dst, op0, op1);
AVT_LONG:
longVectL(dst, op0, op1);
AVT_LONG2:
long2VectL(dst, op0, op1);
AVT_LONG4:
long4VectL(dst, op0, op1);
AVT_LONG8:
long8VectL(dst, op0, op1);
AVT_FLOAT:
floatVectL(dst, op0, op1);
AVT_FLOAT2:
float2VectL(dst, op0, op1);
AVT_FLOAT4:
float4VectL(dst, op0, op1);
AVT_FLOAT8:
float8VectL(dst, op0, op1);
AVT_DOUBLE:
doubleVectL(dst, op0, op1);
AVT_DOUBLE2:
double2VectL(dst, op0, op1);
AVT_DOUBLE4:
double4VectL(dst, op0, op1);
AVT_DOUBLE8:
double8VectL(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_LE: begin
case primitiveKind of
AVT_BYTE:
byteVectLE(dst, op0, op1);
AVT_BYTE2:
byte2VectLE(dst, op0, op1);
AVT_BYTE4:
byte4VectLE(dst, op0, op1);
AVT_BYTE8:
byte8VectLE(dst, op0, op1);
AVT_SHORT:
shortVectLE(dst, op0, op1);
AVT_SHORT2:
short2VectLE(dst, op0, op1);
AVT_SHORT4:
short4VectLE(dst, op0, op1);
AVT_SHORT8:
short8VectLE(dst, op0, op1);
AVT_INT:
intVectLE(dst, op0, op1);
AVT_INT2:
int2VectLE(dst, op0, op1);
AVT_INT4:
int4VectLE(dst, op0, op1);
AVT_INT8:
int8VectLE(dst, op0, op1);
AVT_LONG:
longVectLE(dst, op0, op1);
AVT_LONG2:
long2VectLE(dst, op0, op1);
AVT_LONG4:
long4VectLE(dst, op0, op1);
AVT_LONG8:
long8VectLE(dst, op0, op1);
AVT_FLOAT:
floatVectLE(dst, op0, op1);
AVT_FLOAT2:
float2VectLE(dst, op0, op1);
AVT_FLOAT4:
float4VectLE(dst, op0, op1);
AVT_FLOAT8:
float8VectLE(dst, op0, op1);
AVT_DOUBLE:
doubleVectLE(dst, op0, op1);
AVT_DOUBLE2:
double2VectLE(dst, op0, op1);
AVT_DOUBLE4:
double4VectLE(dst, op0, op1);
AVT_DOUBLE8:
double8VectLE(dst, op0, op1);
else
goto label0;
end;
end;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
case operatorKind of
OPER_SCAL_G, OPER_SCAL_GE, OPER_SCAL_L, OPER_SCAL_LE: begin
if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) or (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind = AVT_FLOAT) or (primitiveKind = AVT_DOUBLE) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := getPrimitiveType(AVT_BOOLEAN);
end else begin
goto label0;
end;
end;
OPER_VECT_G, OPER_VECT_GE, OPER_VECT_L, OPER_VECT_LE: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := typeCommonRef;
end else
if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 7));
end else begin
goto label0;
end;
end;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeReturnRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
until false;
result := pos;
end;
function AVTCodeBuilder.parseEquality(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeReturnRef: AVTType;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseRelational(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
repeat
operatorKind := source.getLexemeType(pos);
case operatorKind of
OPER_SCAL_E, OPER_SCAL_NE, OPER_VECT_E, OPER_VECT_NE: begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, operatorKind, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseRelational(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
end
else
break;
end;
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case operatorKind of
OPER_SCAL_E: begin
case primitiveKind of
AVT_BYTE, AVT_BOOLEAN:
byteScalE(dst, op0, op1);
AVT_BYTE2:
byte2ScalE(dst, op0, op1);
AVT_BYTE4:
byte4ScalE(dst, op0, op1);
AVT_BYTE8:
byte8ScalE(dst, op0, op1);
AVT_SHORT:
shortScalE(dst, op0, op1);
AVT_SHORT2:
short2ScalE(dst, op0, op1);
AVT_SHORT4:
short4ScalE(dst, op0, op1);
AVT_SHORT8:
short8ScalE(dst, op0, op1);
AVT_INT:
intScalE(dst, op0, op1);
AVT_INT2:
int2ScalE(dst, op0, op1);
AVT_INT4:
int4ScalE(dst, op0, op1);
AVT_INT8:
int8ScalE(dst, op0, op1);
AVT_LONG:
longScalE(dst, op0, op1);
AVT_LONG2:
long2ScalE(dst, op0, op1);
AVT_LONG4:
long4ScalE(dst, op0, op1);
AVT_LONG8:
long8ScalE(dst, op0, op1);
AVT_FLOAT:
floatScalE(dst, op0, op1);
AVT_FLOAT2:
float2ScalE(dst, op0, op1);
AVT_FLOAT4:
float4ScalE(dst, op0, op1);
AVT_FLOAT8:
float8ScalE(dst, op0, op1);
AVT_DOUBLE:
doubleScalE(dst, op0, op1);
AVT_DOUBLE2:
double2ScalE(dst, op0, op1);
AVT_DOUBLE4:
double4ScalE(dst, op0, op1);
AVT_DOUBLE8:
double8ScalE(dst, op0, op1);
AVT_REAL:
realScalE(dst, op0, op1);
else
goto label0;
end;
end;
OPER_SCAL_NE: begin
case primitiveKind of
AVT_BYTE, AVT_BOOLEAN:
byteScalNE(dst, op0, op1);
AVT_BYTE2:
byte2ScalNE(dst, op0, op1);
AVT_BYTE4:
byte4ScalNE(dst, op0, op1);
AVT_BYTE8:
byte8ScalNE(dst, op0, op1);
AVT_SHORT:
shortScalNE(dst, op0, op1);
AVT_SHORT2:
short2ScalNE(dst, op0, op1);
AVT_SHORT4:
short4ScalNE(dst, op0, op1);
AVT_SHORT8:
short8ScalNE(dst, op0, op1);
AVT_INT:
intScalNE(dst, op0, op1);
AVT_INT2:
int2ScalNE(dst, op0, op1);
AVT_INT4:
int4ScalNE(dst, op0, op1);
AVT_INT8:
int8ScalNE(dst, op0, op1);
AVT_LONG:
longScalNE(dst, op0, op1);
AVT_LONG2:
long2ScalNE(dst, op0, op1);
AVT_LONG4:
long4ScalNE(dst, op0, op1);
AVT_LONG8:
long8ScalNE(dst, op0, op1);
AVT_FLOAT:
floatScalNE(dst, op0, op1);
AVT_FLOAT2:
float2ScalNE(dst, op0, op1);
AVT_FLOAT4:
float4ScalNE(dst, op0, op1);
AVT_FLOAT8:
float8ScalNE(dst, op0, op1);
AVT_DOUBLE:
doubleScalNE(dst, op0, op1);
AVT_DOUBLE2:
double2ScalNE(dst, op0, op1);
AVT_DOUBLE4:
double4ScalNE(dst, op0, op1);
AVT_DOUBLE8:
double8ScalNE(dst, op0, op1);
AVT_REAL:
realScalNE(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_E: begin
case primitiveKind of
AVT_BYTE:
byteVectE(dst, op0, op1);
AVT_BYTE2:
byte2VectE(dst, op0, op1);
AVT_BYTE4:
byte4VectE(dst, op0, op1);
AVT_BYTE8:
byte8VectE(dst, op0, op1);
AVT_SHORT:
shortVectE(dst, op0, op1);
AVT_SHORT2:
short2VectE(dst, op0, op1);
AVT_SHORT4:
short4VectE(dst, op0, op1);
AVT_SHORT8:
short8VectE(dst, op0, op1);
AVT_INT:
intVectE(dst, op0, op1);
AVT_INT2:
int2VectE(dst, op0, op1);
AVT_INT4:
int4VectE(dst, op0, op1);
AVT_INT8:
int8VectE(dst, op0, op1);
AVT_LONG:
longVectE(dst, op0, op1);
AVT_LONG2:
long2VectE(dst, op0, op1);
AVT_LONG4:
long4VectE(dst, op0, op1);
AVT_LONG8:
long8VectE(dst, op0, op1);
AVT_FLOAT:
floatVectE(dst, op0, op1);
AVT_FLOAT2:
float2VectE(dst, op0, op1);
AVT_FLOAT4:
float4VectE(dst, op0, op1);
AVT_FLOAT8:
float8VectE(dst, op0, op1);
AVT_DOUBLE:
doubleVectE(dst, op0, op1);
AVT_DOUBLE2:
double2VectE(dst, op0, op1);
AVT_DOUBLE4:
double4VectE(dst, op0, op1);
AVT_DOUBLE8:
double8VectE(dst, op0, op1);
else
goto label0;
end;
end;
OPER_VECT_NE: begin
case primitiveKind of
AVT_BYTE:
byteVectNE(dst, op0, op1);
AVT_BYTE2:
byte2VectNE(dst, op0, op1);
AVT_BYTE4:
byte4VectNE(dst, op0, op1);
AVT_BYTE8:
byte8VectNE(dst, op0, op1);
AVT_SHORT:
shortVectNE(dst, op0, op1);
AVT_SHORT2:
short2VectNE(dst, op0, op1);
AVT_SHORT4:
short4VectNE(dst, op0, op1);
AVT_SHORT8:
short8VectNE(dst, op0, op1);
AVT_INT:
intVectNE(dst, op0, op1);
AVT_INT2:
int2VectNE(dst, op0, op1);
AVT_INT4:
int4VectNE(dst, op0, op1);
AVT_INT8:
int8VectNE(dst, op0, op1);
AVT_LONG:
longVectNE(dst, op0, op1);
AVT_LONG2:
long2VectNE(dst, op0, op1);
AVT_LONG4:
long4VectNE(dst, op0, op1);
AVT_LONG8:
long8VectNE(dst, op0, op1);
AVT_FLOAT:
floatVectNE(dst, op0, op1);
AVT_FLOAT2:
float2VectNE(dst, op0, op1);
AVT_FLOAT4:
float4VectNE(dst, op0, op1);
AVT_FLOAT8:
float8VectNE(dst, op0, op1);
AVT_DOUBLE:
doubleVectNE(dst, op0, op1);
AVT_DOUBLE2:
double2VectNE(dst, op0, op1);
AVT_DOUBLE4:
double4VectNE(dst, op0, op1);
AVT_DOUBLE8:
double8VectNE(dst, op0, op1);
else
goto label0;
end;
end;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
case operatorKind of
OPER_SCAL_E, OPER_SCAL_NE: begin
typeReturnRef := getPrimitiveType(AVT_BOOLEAN);
end;
OPER_VECT_E, OPER_VECT_NE: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := typeCommonRef;
end else
if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 7));
end else begin
goto label0;
end;
end;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeReturnRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if (operatorKind = OPER_SCAL_E) or (operatorKind = OPER_SCAL_NE) then begin
if typeCommonRef = nil then begin
dst := AVTConstant.create(getPrimitiveType(AVT_BOOLEAN));
dst.value.asBoolean := operatorKind = OPER_SCAL_E;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
if typeCommonRef is AVTTypeStructured then begin
expressionNode.setData(expressionNode.lineIndex, getPrimitiveType(AVT_BOOLEAN), operatorKind, typeCommonRef);
continue;
end;
end else
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(operatorKind), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator ' + AVTLexer.lexemeToString(operatorKind) + ' is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
until false;
result := pos;
end;
function AVTCodeBuilder.parseBitAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseEquality(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
while source.getLexemeType(pos) = OPER_BIT_AND do begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BIT_AND, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseEquality(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case primitiveKind of
AVT_BYTE, AVT_BOOLEAN:
byteBitAnd(dst, op0, op1);
AVT_BYTE2:
byte2BitAnd(dst, op0, op1);
AVT_BYTE4:
byte4BitAnd(dst, op0, op1);
AVT_BYTE8:
byte8BitAnd(dst, op0, op1);
AVT_SHORT:
shortBitAnd(dst, op0, op1);
AVT_SHORT2:
short2BitAnd(dst, op0, op1);
AVT_SHORT4:
short4BitAnd(dst, op0, op1);
AVT_SHORT8:
short8BitAnd(dst, op0, op1);
AVT_INT:
intBitAnd(dst, op0, op1);
AVT_INT2:
int2BitAnd(dst, op0, op1);
AVT_INT4:
int4BitAnd(dst, op0, op1);
AVT_INT8:
int8BitAnd(dst, op0, op1);
AVT_LONG:
longBitAnd(dst, op0, op1);
AVT_LONG2:
long2BitAnd(dst, op0, op1);
AVT_LONG4:
long4BitAnd(dst, op0, op1);
AVT_LONG8:
long8BitAnd(dst, op0, op1);
else
goto label0;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
if (primitiveKind <> AVT_BOOLEAN) and ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) then begin
goto label0;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeCommonRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(OPER_BIT_AND), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator &' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator & is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
end;
result := pos;
end;
function AVTCodeBuilder.parseBitXor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseBitAnd(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
while source.getLexemeType(pos) = OPER_BIT_XOR do begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BIT_XOR, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseBitAnd(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case primitiveKind of
AVT_BYTE, AVT_BOOLEAN:
byteBitXor(dst, op0, op1);
AVT_BYTE2:
byte2BitXor(dst, op0, op1);
AVT_BYTE4:
byte4BitXor(dst, op0, op1);
AVT_BYTE8:
byte8BitXor(dst, op0, op1);
AVT_SHORT:
shortBitXor(dst, op0, op1);
AVT_SHORT2:
short2BitXor(dst, op0, op1);
AVT_SHORT4:
short4BitXor(dst, op0, op1);
AVT_SHORT8:
short8BitXor(dst, op0, op1);
AVT_INT:
intBitXor(dst, op0, op1);
AVT_INT2:
int2BitXor(dst, op0, op1);
AVT_INT4:
int4BitXor(dst, op0, op1);
AVT_INT8:
int8BitXor(dst, op0, op1);
AVT_LONG:
longBitXor(dst, op0, op1);
AVT_LONG2:
long2BitXor(dst, op0, op1);
AVT_LONG4:
long4BitXor(dst, op0, op1);
AVT_LONG8:
long8BitXor(dst, op0, op1);
else
goto label0;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
if (primitiveKind <> AVT_BOOLEAN) and ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) then begin
goto label0;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeCommonRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(OPER_BIT_XOR), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator ^' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator ^ is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
end;
result := pos;
end;
function AVTCodeBuilder.parseBitOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0;
var
isRight: boolean;
instruction: int;
operatorPos: int;
primitiveKind: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
argumentTypes: Vector;
foundMethod: AVTMethod;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseBitXor(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
while source.getLexemeType(pos) = OPER_BIT_OR do begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BIT_OR, nil);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseBitXor(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if typeCommonRef is AVTTypePrimitive then begin
primitiveKind := AVTTypePrimitive(typeCommonRef).primitiveKind;
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
cast(op0, op0, AVTTypePrimitive(typeCommonRef));
cast(op1, op1, AVTTypePrimitive(typeCommonRef));
dst := AVTConstant.create();
case primitiveKind of
AVT_BYTE, AVT_BOOLEAN:
byteBitOr(dst, op0, op1);
AVT_BYTE2:
byte2BitOr(dst, op0, op1);
AVT_BYTE4:
byte4BitOr(dst, op0, op1);
AVT_BYTE8:
byte8BitOr(dst, op0, op1);
AVT_SHORT:
shortBitOr(dst, op0, op1);
AVT_SHORT2:
short2BitOr(dst, op0, op1);
AVT_SHORT4:
short4BitOr(dst, op0, op1);
AVT_SHORT8:
short8BitOr(dst, op0, op1);
AVT_INT:
intBitOr(dst, op0, op1);
AVT_INT2:
int2BitOr(dst, op0, op1);
AVT_INT4:
int4BitOr(dst, op0, op1);
AVT_INT8:
int8BitOr(dst, op0, op1);
AVT_LONG:
longBitOr(dst, op0, op1);
AVT_LONG2:
long2BitOr(dst, op0, op1);
AVT_LONG4:
long4BitOr(dst, op0, op1);
AVT_LONG8:
long8BitOr(dst, op0, op1);
else
goto label0;
end;
expressionNode.setData(expressionNode.lineIndex, dst.valueType, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
if (primitiveKind <> AVT_BOOLEAN) and ((primitiveKind < AVT_BYTE) or (primitiveKind > AVT_LONG8)) then begin
goto label0;
end;
operand0Node := cast(operand0Node, code, typeCommonRef);
operand1Node := cast(operand1Node, code, typeCommonRef);
expressionNode.dataType := typeCommonRef;
expressionNode.operand1 := typeCommonRef;
continue;
end;
if typeOperand0Ref is AVTTypeStructured then begin
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(typeOperand1Ref, false));
foundMethod := AVTTypeStructured(typeOperand0Ref).findMethod(AVTOperator.operatorToSpecName(OPER_BIT_OR), argumentTypes, typeRef, operatorPos);
isRight := (foundMethod <> nil) and foundMethod.isConvertableArgumentTypes(argumentTypes);
finally
argumentTypes.free();
end;
if isRight then begin
if not foundMethod.isVisible(AVTTypeStructured(typeOperand0Ref), typeRef) then begin
raise AVTCompilerException.create('The operator |' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
cast(operand1Node, code, foundMethod.getArgumentAt(0).valueType);
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
expressionNode.setData(expressionNode.lineIndex, foundMethod.returnType, instruction, foundMethod);
continue;
end;
end;
label0:
dst.free();
raise AVTCompilerException.create('The operator | is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
end;
result := pos;
end;
function AVTCodeBuilder.parseBoolAnd(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
var
operatorPos: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseBitOr(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
while source.getLexemeType(pos) = OPER_BOOL_AND do begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BOOL_AND);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseBitOr(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if (typeCommonRef is AVTTypePrimitive) and typeCommonRef.isBoolean() then begin
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
dst := AVTConstant.create(typeCommonRef);
dst.value.asBoolean := op0.value.asBoolean and op1.value.asBoolean;
expressionNode.setData(expressionNode.lineIndex, typeCommonRef, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
expressionNode.dataType := typeCommonRef;
continue;
end;
dst.free();
raise AVTCompilerException.create('The operator && is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
end;
result := pos;
end;
function AVTCodeBuilder.parseBoolOr(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
var
operatorPos: int;
dst: AVTConstant;
op0: AVTConstant;
op1: AVTConstant;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
begin
pos := parseBoolAnd(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
while source.getLexemeType(pos) = OPER_BOOL_OR do begin
operatorPos := pos;
operand0Node := parentNode.lastChild();
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BOOL_OR);
code.moveNode(operand0Node, expressionNode, 0);
pos := parseBoolAnd(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
dst := nil;
operand1Node := expressionNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
typeOperand1Ref := operand1Node.dataType;
typeCommonRef := commonType(typeOperand0Ref, typeOperand1Ref);
if (typeCommonRef is AVTTypePrimitive) and typeCommonRef.isBoolean() then begin
if (operand0Node.instruction = LOAD_CONST) and (operand1Node.instruction = LOAD_CONST) then begin
op0 := operand0Node.operand1 as AVTConstant;
op1 := operand1Node.operand1 as AVTConstant;
dst := AVTConstant.create(typeCommonRef);
dst.value.asBoolean := op0.value.asBoolean or op1.value.asBoolean;
expressionNode.setData(expressionNode.lineIndex, typeCommonRef, LOAD_CONST, dst);
code.removeNode(operand1Node);
code.removeNode(operand0Node);
continue;
end;
expressionNode.dataType := typeCommonRef;
continue;
end;
dst.free();
raise AVTCompilerException.create('The operator || is undefined for the argument types ' + itemToString(typeOperand0Ref) + ', ' + itemToString(typeOperand1Ref), source, operatorPos);
end;
result := pos;
end;
function AVTCodeBuilder.parseConditional(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
var
operatorPos: int;
typeCommonRef: AVTType;
typeOperand0Ref: AVTType;
typeOperand1Ref: AVTType;
typeOperand2Ref: AVTType;
expressionNode: AVTNode;
operand0Node: AVTNode;
operand1Node: AVTNode;
operand2Node: AVTNode;
begin
pos := parseBoolOr(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
if source.getLexemeType(pos) = CHAR_QUESTION then begin
operand0Node := parentNode.lastChild();
typeOperand0Ref := operand0Node.dataType;
if (typeOperand0Ref = nil) or not typeOperand0Ref.isBoolean() then begin
raise AVTCompilerException.create('The operator ?: is undefined for the argument type ' + itemToString(typeOperand0Ref), source, pos);
end;
expressionNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), nil, OPER_BOOL_COND);
code.moveNode(operand0Node, expressionNode, 0);
operatorPos := parseExpression(expressionNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
if source.getLexemeType(operatorPos) <> CHAR_COLON then begin
raise AVTCompilerException.create('":" expected', source, operatorPos);
end;
operand1Node := expressionNode.lastChild();
code.appendNode(expressionNode).setData(source.getLexemeLineIndex(operatorPos), getPrimitiveType(AVT_VOID), JUMP);
pos := parseExpression(expressionNode, code, methodRef, typeRef, source, operatorPos + 1, ignoreInstanceMembers);
operand2Node := expressionNode.lastChild();
needValue(operand1Node, code);
needValue(operand2Node, code);
typeOperand1Ref := operand1Node.dataType;
typeOperand2Ref := operand2Node.dataType;
typeCommonRef := commonType(typeOperand1Ref, typeOperand2Ref);
if typeCommonRef is AVTTypeInvalid then begin
raise AVTCompilerException.create('The operator ?: is undefined for the argument types ' + itemToString(typeOperand1Ref) + ', ' + itemToString(typeOperand2Ref), source, operatorPos);
end;
cast(operand1Node, code, typeCommonRef);
cast(operand2Node, code, typeCommonRef);
expressionNode.dataType := typeCommonRef;
end;
result := pos;
end;
function AVTCodeBuilder.parseExpression(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; ignoreInstanceMembers: boolean): int;
label
label0, label1;
var
i: int;
lineIndex: int;
lexemeType: int;
instruction: int;
operatorPos: int;
operatorKind: int;
primitiveKind: int;
argumentTypes: Vector;
foundField: AVTField;
foundMethod: AVTMethod;
foundMethodSet: AVTMethod;
foundProperty: AVTProperty;
foundVariable: AVTVariable;
operandNode: AVTNode;
operatorNode: AVTNode;
leftSideNode: AVTNode;
rightSideNode: AVTNode;
typeVoidRef: AVTType;
typeReturnRef: AVTType;
typeLeftSideRef: AVTType;
typeRightSideRef: AVTType;
typeDereferenceRef: AVTTypeStructured;
begin
pos := parseConditional(parentNode, code, methodRef, typeRef, source, pos, ignoreInstanceMembers);
lexemeType := source.getLexemeType(pos);
case lexemeType of
CHAR_EQUALS: begin
operatorPos := pos;
leftSideNode := parentNode.lastChild();
instruction := leftSideNode.instruction;
case instruction of
LOAD_VARIABLE: begin
typeLeftSideRef := (leftSideNode.operand1 as AVTVariable).valueType;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
leftSideNode.dataType := getPrimitiveType(AVT_VOID);
leftSideNode.instruction := STORE_VARIABLE;
end;
LOAD_STATIC: begin
foundField := leftSideNode.operand1 as AVTField;
if foundField.isFinal() and (not(methodRef is AVTClassInit) or (foundField.parentType <> methodRef.parentType) or (foundField.implementationPosition >= 0)) then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundField.valueType;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
leftSideNode.dataType := getPrimitiveType(AVT_VOID);
leftSideNode.instruction := STORE_STATIC;
end;
GET_FIELD: begin
foundField := leftSideNode.operand1 as AVTField;
operandNode := leftSideNode[0];
if foundField.isFinal() and (not(methodRef is AVTInstInit) or (foundField.parentType <> methodRef.parentType) or (operandNode.instruction <> LOAD_VARIABLE) or (operandNode.operand1 <> methodRef.argumentThis)) then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundField.valueType;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
leftSideNode.dataType := getPrimitiveType(AVT_VOID);
leftSideNode.instruction := SET_FIELD;
end;
GET_PROPERTY, SET_PROPERTY: begin
if leftSideNode.length > 1 then begin
raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
end;
foundProperty := leftSideNode.operand1 as AVTProperty;
if foundProperty.writeSynthetic = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundProperty.valueType;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
leftSideNode.dataType := getPrimitiveType(AVT_VOID);
leftSideNode.instruction := SET_PROPERTY;
end;
GET_ARRAY_ELEMENT: begin
typeLeftSideRef := leftSideNode.operand1 as AVTType;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
leftSideNode.dataType := getPrimitiveType(AVT_VOID);
leftSideNode.instruction := SET_ARRAY_ELEMENT;
end;
INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
foundMethod := leftSideNode.operand1 as AVTMethod;
if foundMethod is AVTOperator then begin
operatorKind := AVTOperator(foundMethod).operatorKind;
end else begin
operatorKind := -1;
end;
if (operatorKind = GET_ARRAY_ELEMENT) or (operatorKind = SET_ARRAY_ELEMENT) then begin
if leftSideNode.length > 2 then begin
raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
end;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
typeDereferenceRef := leftSideNode[0].dataType as AVTTypeStructured;
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(leftSideNode[1].dataType, false));
argumentTypes.append(ValueOfObject.create(typeRightSideRef, false));
foundMethod := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, operatorPos);
if (foundMethod = nil) or not foundMethod.isConvertableArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, operatorPos);
end;
finally
argumentTypes.free();
end;
if not foundMethod.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator []=' + foundMethod.argumentsToString() + ' in the type ' + foundMethod.parentType.fullName + ' is not visible', source, operatorPos);
end;
if (instruction = INVOKE_SPECIAL) and foundMethod.isAbstract() then begin
raise AVTCompilerException.create('Can not directly invoke abstract operator []=' + foundMethod.argumentsToString() + ' from the type ' + foundMethod.parentType.fullName, source, operatorPos);
end;
for i := foundMethod.getArgumentsCount() - 1 downto 0 do begin
cast(leftSideNode[i + 1], code, foundMethod.getArgumentAt(i).valueType);
end;
if (instruction <> INVOKE_SPECIAL) or foundMethod.isAbstract() then begin
if foundMethod.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
end;
leftSideNode.setData(leftSideNode.lineIndex, getPrimitiveType(AVT_VOID), instruction, foundMethod);
end else begin
foundProperty := foundMethod.linkedProperty;
if (leftSideNode.length > 1) or (foundProperty = nil) or ((foundProperty.readSynthetic <> foundMethod) and (foundProperty.writeSynthetic <> foundMethod)) then begin
raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
end;
foundMethod := foundProperty.writeSynthetic;
if foundMethod = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
end;
pos := parseExpression(leftSideNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := leftSideNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
typeLeftSideRef := foundProperty.valueType;
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
leftSideNode.dataType := getPrimitiveType(AVT_VOID);
leftSideNode.operand1 := foundMethod;
end;
end
else
raise AVTCompilerException.create('The operator = applicable only to variables, properties and array elements', source, operatorPos);
end;
end;
ASGN_BIT_AND, ASGN_BIT_OR, ASGN_BIT_XOR,
ASGN_SCAL_MUL, ASGN_SCAL_DIV, ASGN_SCAL_DIVU, ASGN_SCAL_REM, ASGN_SCAL_REMU,
ASGN_SCAL_ADD, ASGN_SCAL_SUB, ASGN_SCAL_SAR, ASGN_SCAL_SAL, ASGN_SCAL_SHR,
ASGN_VECT_MUL, ASGN_VECT_DIV, ASGN_VECT_ADD, ASGN_VECT_SUB, ASGN_VECT_SAR, ASGN_VECT_SAL, ASGN_VECT_SHR,
ASGN_VECT_G, ASGN_VECT_GE, ASGN_VECT_L, ASGN_VECT_LE, ASGN_VECT_E, ASGN_VECT_NE,
ASGN_VECT_MULS, ASGN_VECT_ADDS, ASGN_VECT_SUBS, ASGN_VECT_MULU, ASGN_VECT_ADDU, ASGN_VECT_SUBU: begin
operatorPos := pos;
operatorKind := lexemeType - 256;
leftSideNode := parentNode.lastChild();
lineIndex := source.getLexemeLineIndex(pos);
operatorNode := code.appendNode(leftSideNode, lineIndex, nil, operatorKind, nil);
pos := parseExpression(operatorNode, code, methodRef, typeRef, source, pos + 1, ignoreInstanceMembers);
rightSideNode := operatorNode.lastChild();
needValue(rightSideNode, code);
typeRightSideRef := rightSideNode.dataType;
if (typeRightSideRef = nil) or not typeRightSideRef.isNumeric() and not typeRightSideRef.isBoolean() then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= is undefined for the argument type ' + itemToString(typeRightSideRef), source, operatorPos);
end;
instruction := leftSideNode.instruction;
case instruction of
LOAD_VARIABLE: begin
foundVariable := leftSideNode.operand1 as AVTVariable;
typeLeftSideRef := foundVariable.valueType;
typeVoidRef := getPrimitiveType(AVT_VOID);
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, LOAD_VARIABLE, foundVariable);
leftSideNode.dataType := typeVoidRef;
leftSideNode.instruction := STORE_VARIABLE;
end;
LOAD_STATIC: begin
foundField := leftSideNode.operand1 as AVTField;
if foundField.isFinal() then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundField.valueType;
typeVoidRef := getPrimitiveType(AVT_VOID);
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, LOAD_STATIC, foundField);
leftSideNode.dataType := typeVoidRef;
leftSideNode.instruction := STORE_STATIC;
end;
GET_FIELD: begin
foundField := leftSideNode.operand1 as AVTField;
if foundField.isFinal() then begin
raise AVTCompilerException.create('The final field ' + foundField.fullName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundField.valueType;
typeVoidRef := getPrimitiveType(AVT_VOID);
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, GET_FIELD, foundField);
code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP1);
leftSideNode.dataType := typeVoidRef;
leftSideNode.instruction := SET_FIELD;
end;
GET_PROPERTY: begin
foundProperty := leftSideNode.operand1 as AVTProperty;
if foundProperty.writeSynthetic = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundProperty.valueType;
typeVoidRef := getPrimitiveType(AVT_VOID);
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, GET_PROPERTY, foundProperty);
code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP1);
leftSideNode.dataType := typeVoidRef;
leftSideNode.instruction := SET_PROPERTY;
end;
GET_ARRAY_ELEMENT: begin
typeLeftSideRef := leftSideNode.operand1 as AVTType;
typeVoidRef := getPrimitiveType(AVT_VOID);
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, GET_ARRAY_ELEMENT, typeLeftSideRef);
code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP2);
leftSideNode.dataType := typeVoidRef;
leftSideNode.instruction := SET_ARRAY_ELEMENT;
end;
INVOKE_SPECIAL, INVOKE_VIRTUAL, INVOKE_SERVICE: begin
foundMethod := leftSideNode.operand1 as AVTMethod;
if (foundMethod is AVTOperator) and (AVTOperator(foundMethod).operatorKind = GET_ARRAY_ELEMENT) then begin
typeLeftSideRef := foundMethod.returnType;
typeVoidRef := getPrimitiveType(AVT_VOID);
typeDereferenceRef := leftSideNode[0].dataType as AVTTypeStructured;
argumentTypes := Vector.create();
try
argumentTypes.append(ValueOfObject.create(leftSideNode[1].dataType, false));
argumentTypes.append(ValueOfObject.create(typeLeftSideRef, false));
foundMethodSet := typeDereferenceRef.findMethod(AVTOperator.operatorToSpecName(SET_ARRAY_ELEMENT), argumentTypes, typeRef, operatorPos);
if (foundMethodSet = nil) or not foundMethodSet.isIdentityArgumentTypes(argumentTypes) then begin
raise AVTCompilerException.create('The operator []=' + argumentTypes.toString() + ' is undefined for the type ' + typeDereferenceRef.fullName, source, operatorPos);
end;
finally
argumentTypes.free();
end;
if not foundMethodSet.isVisible(typeDereferenceRef, typeRef) then begin
raise AVTCompilerException.create('The operator []=' + foundMethodSet.argumentsToString() + ' in the type ' + foundMethodSet.parentType.fullName + ' is not visible', source, operatorPos);
end;
if (instruction = INVOKE_SPECIAL) and foundMethodSet.isAbstract() then begin
raise AVTCompilerException.create('Can not directly invoke abstract operator []=' + foundMethodSet.argumentsToString() + ' from the type ' + foundMethodSet.parentType.fullName, source, operatorPos);
end;
for i := foundMethodSet.getArgumentsCount() - 1 downto 0 do begin
cast(leftSideNode[i + 1], code, foundMethodSet.getArgumentAt(i).valueType);
end;
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, instruction, foundMethod);
code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP2);
if (instruction <> INVOKE_SPECIAL) or foundMethodSet.isAbstract() then begin
if foundMethodSet.parentType.isService() then begin
instruction := INVOKE_SERVICE;
end else begin
instruction := INVOKE_VIRTUAL;
end;
end;
leftSideNode.setData(leftSideNode.lineIndex, typeVoidRef, instruction, foundMethodSet);
end else begin
foundProperty := foundMethod.linkedProperty;
if (foundProperty = nil) or (foundProperty.readSynthetic <> foundMethod) then begin
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= applicable only to variables, properties and array elements', source, operatorPos);
end;
foundMethodSet := foundProperty.writeSynthetic;
if foundMethodSet = nil then begin
raise AVTCompilerException.create('The read-only property ' + foundProperty.simpleName + ' can not be assigned', source, operatorPos);
end;
typeLeftSideRef := foundProperty.valueType;
typeVoidRef := getPrimitiveType(AVT_VOID);
operandNode := code.insertNode(operatorNode, 0, lineIndex, typeLeftSideRef, instruction, foundMethod);
code.appendNode(operandNode).setData(lineIndex, typeVoidRef, DUP1);
leftSideNode.setData(leftSideNode.lineIndex, typeVoidRef, instruction, foundMethodSet);
end;
end
else
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= applicable only to variables, properties and array elements', source, operatorPos);
end;
case operatorKind of
OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR, OPER_VECT_SAR, OPER_VECT_SAL, OPER_VECT_SHR: begin
if not getPrimitiveType(AVT_INT).isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to int', source, operatorPos);
end;
end
else
if not typeLeftSideRef.isConvertableFrom(typeRightSideRef) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(typeRightSideRef) + ' to ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
cast(rightSideNode, code, typeLeftSideRef);
end;
primitiveKind := (typeLeftSideRef as AVTTypePrimitive).primitiveKind;
begin
begin
case operatorKind of
OPER_BIT_AND, OPER_BIT_OR, OPER_BIT_XOR: begin
if (primitiveKind = AVT_BOOLEAN) or (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
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: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_MUL, OPER_SCAL_ADD, OPER_SCAL_SUB: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_DIV, OPER_SCAL_DIVU: begin
if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
typeReturnRef := getPrimitiveType(AVT_INT);
end else
if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_REM, OPER_SCAL_REMU: begin
if (primitiveKind = AVT_BYTE) or (primitiveKind = AVT_SHORT) then begin
typeReturnRef := getPrimitiveType(AVT_INT);
end else
if (primitiveKind = AVT_INT) or (primitiveKind = AVT_LONG) or (primitiveKind = AVT_FLOAT) or (primitiveKind = AVT_DOUBLE) or (primitiveKind = AVT_REAL) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_SCAL_SAR, OPER_SCAL_SAL, OPER_SCAL_SHR: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := getPrimitiveType(AVT_INT + (primitiveKind and 3));
end else
if (primitiveKind >= AVT_INT) and (primitiveKind <= AVT_LONG8) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_VECT_MUL, OPER_VECT_ADD, OPER_VECT_SUB: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_VECT_DIV: begin
if (primitiveKind >= AVT_FLOAT) and (primitiveKind <= AVT_DOUBLE8) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
OPER_VECT_MULS, OPER_VECT_ADDS, OPER_VECT_SUBS, OPER_VECT_MULU, OPER_VECT_ADDU, OPER_VECT_SUBU: begin
if (primitiveKind >= AVT_BYTE) and (primitiveKind <= AVT_SHORT8) then begin
typeReturnRef := typeLeftSideRef;
end else begin
goto label0;
end;
end;
end;
goto label1;
end;
label0:
raise AVTCompilerException.create('The operator ' + AVTOperator.operatorToChar(operatorKind) + '= is undefined for the argument type ' + itemToString(typeLeftSideRef), source, operatorPos);
end;
label1:
operatorNode.dataType := typeReturnRef;
operatorNode.operand1 := typeLeftSideRef;
if typeReturnRef <> typeLeftSideRef then begin
cast(operatorNode, code, typeLeftSideRef);
end;
end;
end;
result := pos;
end;
function AVTCodeBuilder.parseLocal(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int; variableAllowed: boolean): int;
var
namePos: int;
lineIndex: int;
name: AnsiString;
expType: AVTType;
expNode: AVTNode;
varType: AVTType;
varNode: AVTNode;
varValue: AVTConstant;
begin
if variableAllowed then begin
varType := tryParseType(parentNode, methodRef, typeRef, source, pos);
namePos := source.position;
end else begin
varType := nil;
namePos := 0;
end;
if (varType <> nil) and (source.getLexemeType(namePos) = LITR_NAME) then begin
name := source.getLexemeAnsiString(namePos);
if varType.isVoid() then begin
raise AVTCompilerException.create('void is an invalid type for the variable ' + name, source, namePos);
end;
if getVariable(name, parentNode, methodRef) <> nil then begin
raise AVTCompilerException.create('Duplicate local variable ' + name, source, namePos);
end;
lineIndex := source.getLexemeLineIndex(namePos);
varNode := code.appendNode(parentNode);
pos := namePos + 1;
if source.getLexemeType(pos) <> CHAR_EQUALS then begin
varValue := AVTConstant.create(varType);
varValue.value.isNull := true;
code.appendNode(varNode).setData(lineIndex, varType, LOAD_CONST, varValue);
end else begin
pos := parseExpression(varNode, code, methodRef, typeRef, source, pos + 1);
expNode := varNode.lastChild();
needValue(expNode, code);
expType := expNode.dataType;
if not varType.isConvertableFrom(expType) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expType) + ' to ' + itemToString(varType), source, namePos + 1);
end;
cast(expNode, code, varType);
end;
varNode.setData(lineIndex, getPrimitiveType(AVT_VOID), DECLARE_VARIABLE, AVTVariable.create(varType, name, source, namePos));
end else begin
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
expNode := parentNode.lastChild();
case expNode.instruction of
STORE_VARIABLE, STORE_STATIC, SET_FIELD, SET_PROPERTY, SET_ARRAY_ELEMENT,
INVOKE_STATIC, INVOKE_SPECIAL, INVOKE_SERVICE, INVOKE_VIRTUAL, NEW_CLASS, NEW_SERVICE,
OPER_INCREMENT, OPER_DECREMENT, OPER_INC_POST, OPER_DEC_POST, OPER_INC_PRED, OPER_DEC_PRED:
discardValue(expNode, code)
else
raise AVTCompilerException.create('Method invokation or assignment expected', source, pos);
end;
end;
result := pos;
end;
function AVTCodeBuilder.parseBlock(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
begin
while source.getLexemeType(pos) <> CHAR_CURLY_CLOSED do begin
pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos);
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseDo(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
expressionNode: AVTNode;
expressionType: AVTType;
begin
pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos);
if source.getLexemeType(pos) <> AVT_WHILE then begin
raise AVTCompilerException.create('"while" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if (expressionType = nil) or not expressionType.isBoolean() then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
end;
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseIf(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
expressionNode: AVTNode;
expressionType: AVTType;
begin
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if (expressionType = nil) or not expressionType.isBoolean() then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
end;
pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
if source.getLexemeType(pos) = AVT_ELSE then begin
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), JUMP);
pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
end;
result := pos;
end;
function AVTCodeBuilder.parseFor(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
index: int;
stepNode: AVTNode;
expressionNode: AVTNode;
expressionType: AVTType;
typeBooleanRef: AVTType;
typeVoidRef: AVTType;
trueConstant: AVTConstant;
begin
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
inc(pos);
{ инициализация }
if source.getLexemeType(pos) <> CHAR_SEMICOLON then repeat
pos := parseLocal(parentNode, code, methodRef, typeRef, source, pos);
case source.getLexemeType(pos) of
CHAR_COMMA: begin
inc(pos);
end;
CHAR_SEMICOLON: begin
break;
end
else
raise AVTCompilerException.create('";" expected', source, pos);
end;
until false;
typeVoidRef := getPrimitiveType(AVT_VOID);
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeVoidRef, JUMP);
inc(pos);
{ условие повтора }
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
end else begin
typeBooleanRef := getPrimitiveType(AVT_BOOLEAN);
trueConstant := AVTConstant.create(typeBooleanRef);
trueConstant.value.asBoolean := true;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeBooleanRef, LOAD_CONST, trueConstant);
end;
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if (expressionType = nil) or not expressionType.isBoolean() then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
end;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
{ шаг }
stepNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_BLOCK);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then repeat
pos := parseLocal(stepNode, code, methodRef, typeRef, source, pos, false);
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;
{ тело цикла }
pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
{ перестановка узлов }
index := parentNode.length;
code.moveNode(stepNode, index);
code.moveNode(expressionNode, index);
result := pos;
end;
function AVTCodeBuilder.parseTry(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
catchAdded: boolean;
name: AnsiString;
lineIndex: int;
blockNode: AVTNode;
catchNode: AVTNode;
tryEndNode: AVTNode;
typeVoidRef: AVTType;
typeParsedRef: AVTType;
typeThrowableRef: AVTType;
begin
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
typeVoidRef := getPrimitiveType(AVT_VOID);
blockNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_BLOCK);
pos := parseBlock(blockNode, code, methodRef, typeRef, source, pos + 1);
lineIndex := source.getLexemeLineIndex(pos - 1);
tryEndNode := code.appendNode(parentNode, lineIndex, typeVoidRef, AVT_TRY_END);
code.appendNode(parentNode, lineIndex, typeVoidRef, JUMP);
case source.getLexemeType(pos) of
AVT_CATCH: begin
catchAdded := false;
typeThrowableRef := getThrowableType();
repeat
if catchAdded then begin
code.appendNode(parentNode.lastChild(), source.getLexemeLineIndex(pos - 1), typeVoidRef, JUMP);
end;
lineIndex := source.getLexemeLineIndex(pos);
inc(pos);
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
typeParsedRef := parseType(parentNode, methodRef, typeRef, source, pos + 1);
if not typeParsedRef.isClass() or not typeThrowableRef.isAssignableFrom(typeParsedRef) then begin
raise AVTCompilerException.create('No exception of type ' + itemToString(typeParsedRef) + ' can be thrown; an exception type must be a subclass of ' + itemToString(typeThrowableRef), source, pos);
end;
pos := source.position;
if source.getLexemeType(pos) <> LITR_NAME then begin
raise AVTCompilerException.create('Variable name expected', source, pos);
end;
name := source.getLexemeAnsiString(pos);
if getVariable(name, parentNode.parent, methodRef) <> nil then begin
raise AVTCompilerException.create('Duplicate local variable ' + name, source, pos);
end;
catchNode := code.appendNode(parentNode, lineIndex, typeVoidRef, AVT_CATCH, AVTVariable.create(typeParsedRef, name, source, pos));
inc(pos);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
pos := parseBlock(catchNode, code, methodRef, typeRef, source, pos + 1);
catchAdded := true;
until source.getLexemeType(pos) <> AVT_CATCH;
end;
AVT_FINALLY: begin
catchNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_FINALLY);
code.appendNode(tryEndNode).setData(tryEndNode.lineIndex, typeVoidRef, AVT_FINALLY_INVOKE, catchNode);
inc(pos);
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
pos := parseBlock(catchNode, code, methodRef, typeRef, source, pos + 1);
code.appendNode(catchNode, source.getLexemeLineIndex(pos - 1), typeVoidRef, AVT_FINALLY_RETURN);
end
else
raise AVTCompilerException.create('"catch" or "finally" expected', source, pos);
end;
result := pos;
end;
function AVTCodeBuilder.parseWith(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
typeVoidRef: AVTType;
variableNode: AVTNode;
expressionNode: AVTNode;
expressionType: AVTType;
begin
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
inc(pos);
typeVoidRef := getPrimitiveType(AVT_VOID);
repeat
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if not(expressionType is AVTTypeStructured) then begin
raise AVTCompilerException.create(itemToString(expressionType) + ' is not a valid type''s argument for the with statement', source, pos);
end;
variableNode := code.appendNode(parentNode);
variableNode.setData(NO_LINE_INDEX, typeVoidRef, DECLARE_VARIABLE, methodRef.createWithVariable(AVTTypeStructured(expressionType)));
code.moveNode(expressionNode, variableNode, 0);
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;
result := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
end;
function AVTCodeBuilder.parseBreak(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
label
label0;
var
labelName: UnicodeString;
currentNode: AVTNode;
begin
if source.getLexemeType(pos) <> LITR_NAME then begin
currentNode := parentNode.parent;
while currentNode <> nil do begin
case currentNode.instruction of
AVT_DO, AVT_FOR, AVT_WHILE, AVT_SWITCH:
goto label0;
end;
currentNode := currentNode.parent;
end;
raise AVTCompilerException.create('Break can not be used outside of a loop or a switch', source, pos);
end else begin
labelName := source.getLexemeUnicodeString(pos);
currentNode := parentNode.parent;
while currentNode <> nil do begin
if (currentNode.instruction = AVT_LABEL) and ((currentNode.operand1 as AVTConstant).value.asString = labelName) then begin
inc(pos);
goto label0;
end;
currentNode := currentNode.parent;
end;
raise AVTCompilerException.create('The label ' + stringToUTF8(labelName) + ' is missing', source, pos);
end;
label0:
parentNode.operand1 := currentNode;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseThrow(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
expressionNode: AVTNode;
expressionType: AVTType;
typeThrowableRef: AVTType;
begin
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
typeThrowableRef := getThrowableType();
if not typeThrowableRef.isAssignableFrom(expressionType) then begin
raise AVTCompilerException.create('No exception of type ' + itemToString(expressionType) + ' can be thrown; an exception type must be a subclass of ' + itemToString(typeThrowableRef), source, pos);
end;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseWhile(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
expressionNode: AVTNode;
expressionType: AVTType;
begin
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if (expressionType = nil) or not expressionType.isBoolean() then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to boolean', source, pos);
end;
pos := parseStatement(parentNode, code, methodRef, typeRef, source, pos + 1);
code.moveNode(expressionNode, 2);
code.insertNode(parentNode).setData(-1, getPrimitiveType(AVT_VOID), JUMP);
result := pos;
end;
function AVTCodeBuilder.parseReturn(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
typeReturnRef: AVTType;
expressionType: AVTType;
expressionNode: AVTNode;
begin
typeReturnRef := methodRef.returnType;
if not typeReturnRef.isVoid() then begin
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos);
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if not typeReturnRef.isConvertableFrom(expressionType) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to ' + itemToString(typeReturnRef), source, pos);
end;
cast(expressionNode, code, typeReturnRef);
end;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseSwitch(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
hasDefault: boolean;
hasValues: Vector;
expressionNode: AVTNode;
expressionType: AVTType;
valueConst: AVTConstant;
valueAsObject: Value;
valueType: AVTType;
valueNode: AVTNode;
blockNode: AVTNode;
typeVoidRef: AVTType;
typeIntRef: AVTTypePrimitive;
begin
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
expressionNode := parentNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
typeIntRef := getPrimitiveType(AVT_INT);
if not typeIntRef.isConvertableFrom(expressionType) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(expressionType) + ' to int', source, pos);
end;
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
inc(pos);
typeVoidRef := getPrimitiveType(AVT_VOID);
blockNode := nil;
hasDefault := false;
hasValues := Vector.create();
try
repeat
case source.getLexemeType(pos) of
AVT_CASE: begin
blockNode := nil;
pos := parseExpression(parentNode, code, methodRef, typeRef, source, pos + 1);
valueNode := parentNode.lastChild();
if valueNode.instruction <> LOAD_CONST then begin
raise AVTCompilerException.create('Case expressions must be constant expressions', source, pos);
end;
valueType := valueNode.dataType;
if not expressionType.isConvertableFrom(valueType) then begin
raise AVTCompilerException.create('Type mismatch: can not convert from ' + itemToString(valueType) + ' to ' + itemToString(expressionType), source, pos);
end;
valueConst := valueNode.operand1 as AVTConstant;
cast(valueConst, valueConst, typeIntRef);
valueAsObject := ValueOfLong.create(valueConst.value.asInt, pascalx.lang.TYPE_INT);
if hasValues.contains(valueAsObject) then begin
raise AVTCompilerException.create('Duplicate case', source, pos);
end;
if source.getLexemeType(pos) <> CHAR_COLON then begin
raise AVTCompilerException.create('":" expected', source, pos);
end;
valueNode.setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_CASE, valueConst);
hasValues.append(valueAsObject);
inc(pos);
end;
AVT_DEFAULT: begin
blockNode := nil;
inc(pos);
if hasDefault then begin
raise AVTCompilerException.create('The default case already defined', source, pos);
end;
if source.getLexemeType(pos) <> CHAR_COLON then begin
raise AVTCompilerException.create('":" expected', source, pos);
end;
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_DEFAULT);
hasDefault := true;
inc(pos);
end;
CHAR_CURLY_CLOSED: begin
if not hasDefault then begin
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), typeVoidRef, AVT_DEFAULT);
end;
break;
end
else
if not hasDefault and hasValues.isEmpty() then begin
raise AVTCompilerException.create('"case" or "default" expected', source, pos);
end;
if blockNode = nil then begin
blockNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_BLOCK);
end;
pos := parseStatement(blockNode, code, methodRef, typeRef, source, pos);
end;
until false;
finally
hasValues.free();
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseContinue(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
label
label0;
var
labelName: UnicodeString;
currentNode: AVTNode;
begin
if source.getLexemeType(pos) <> LITR_NAME then begin
currentNode := parentNode.parent;
while currentNode <> nil do begin
case currentNode.instruction of
AVT_DO, AVT_FOR, AVT_WHILE:
goto label0;
end;
currentNode := currentNode.parent;
end;
raise AVTCompilerException.create('Continue can not be used outside of a loop', source, pos);
end else begin
labelName := source.getLexemeUnicodeString(pos);
currentNode := parentNode.parent;
while currentNode <> nil do begin
if (currentNode.instruction = AVT_LABEL) and ((currentNode.operand1 as AVTConstant).value.asString = labelName) then begin
currentNode := currentNode.firstChild();
case currentNode.instruction of
AVT_DO, AVT_FOR, AVT_WHILE: begin
inc(pos);
goto label0;
end
else
raise AVTCompilerException.create('Continue can not be used outside of a loop', source, pos);
end;
end;
currentNode := currentNode.parent;
end;
raise AVTCompilerException.create('The label ' + stringToUTF8(labelName) + ' is missing', source, pos);
end;
label0:
parentNode.operand1 := currentNode;
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
result := pos + 1;
end;
function AVTCodeBuilder.parseSynchronized(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
isWith: boolean;
lineIndex: int;
tryNode: AVTNode;
catchNode: AVTNode;
storeNode: AVTNode;
blockNode: AVTNode;
tryEndNode: AVTNode;
typeVoidRef: AVTType;
monitorVar: AVTVariable;
expressionNode: AVTNode;
expressionType: AVTType;
begin
isWith := false;
if source.getLexemeType(pos) = AVT_WITH then begin
isWith := true;
inc(pos);
end;
if source.getLexemeType(pos) <> CHAR_PARENTH_OPENED then begin
raise AVTCompilerException.create('"(" expected', source, pos);
end;
storeNode := code.appendNode(parentNode);
pos := parseExpression(storeNode, code, methodRef, typeRef, source, pos + 1);
expressionNode := storeNode.lastChild();
needValue(expressionNode, code);
expressionType := expressionNode.dataType;
if not(expressionType is AVTTypeStructured) then begin
raise AVTCompilerException.create(itemToString(expressionType) + ' is not a valid type''s argument for the synchronized statement', source, pos);
end;
typeVoidRef := getPrimitiveType(AVT_VOID);
if isWith then begin
monitorVar := methodRef.createWithVariable(AVTTypeStructured(expressionType));
end else begin
monitorVar := methodRef.createMonitorVariable(AVTTypeStructured(expressionType));
end;
lineIndex := source.getLexemeLineIndex(pos);
storeNode.setData(lineIndex, typeVoidRef, DECLARE_VARIABLE, monitorVar);
code.appendNode(storeNode).setData(lineIndex, typeVoidRef, DUP1);
if source.getLexemeType(pos) <> CHAR_PARENTH_CLOSED then begin
raise AVTCompilerException.create('")" expected', source, pos);
end;
inc(pos);
if source.getLexemeType(pos) <> CHAR_CURLY_OPENED then begin
raise AVTCompilerException.create('"{" expected', source, pos);
end;
lineIndex := source.getLexemeLineIndex(pos);
tryNode := code.appendNode(parentNode, lineIndex, typeVoidRef, AVT_TRY_BEGIN);
blockNode := code.appendNode(tryNode, lineIndex, typeVoidRef, AVT_BLOCK);
pos := parseBlock(blockNode, code, methodRef, typeRef, source, pos + 1);
lineIndex := source.getLexemeLineIndex(pos - 1);
tryEndNode := code.appendNode(tryNode, lineIndex, typeVoidRef, AVT_TRY_END);
code.appendNode(tryNode, lineIndex, typeVoidRef, JUMP);
catchNode := code.appendNode(tryNode, lineIndex, typeVoidRef, AVT_FINALLY);
code.appendNode(tryEndNode).setData(lineIndex, typeVoidRef, AVT_FINALLY_INVOKE, catchNode);
storeNode := code.appendNode(catchNode, lineIndex, typeVoidRef, AVT_MONITOR_LEAVE);
code.appendNode(storeNode).setData(lineIndex, expressionType, LOAD_VARIABLE, monitorVar);
code.appendNode(catchNode).setData(lineIndex, typeVoidRef, AVT_FINALLY_RETURN);
result := pos;
end;
function AVTCodeBuilder.parseStatement(parentNode: AVTNode; code: AVTCode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): int;
var
typeVoidRef: AVTType;
statementNode: AVTNode;
labelConstant: AVTConstant;
begin
typeVoidRef := nil;
while (source.getLexemeType(pos) = LITR_NAME) and (source.getLexemeType(pos + 1) = CHAR_COLON) do begin
if typeVoidRef = nil then typeVoidRef := getPrimitiveType(AVT_VOID);
labelConstant := AVTConstant.create();
labelConstant.value.asString := source.getLexemeUnicodeString(pos);
parentNode := code.appendNode(parentNode, source.getLexemeLineIndex(pos), typeVoidRef, AVT_LABEL, labelConstant);
inc(pos, 2);
end;
case source.getLexemeType(pos) of
AVT_SYNCHRONIZED: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_MONITOR_ENTER);
pos := parseSynchronized(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_CONTINUE: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), nil, AVT_CONTINUE, nil);
pos := parseContinue(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_SWITCH: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_SWITCH);
pos := parseSwitch(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_RETURN: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_RETURN);
pos := parseReturn(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_WHILE: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_WHILE);
pos := parseWhile(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_THROW: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_THROW);
pos := parseThrow(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_BREAK: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), nil, AVT_BREAK, nil);
pos := parseBreak(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_WITH: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_WITH);
pos := parseWith(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_TRY_BEGIN: begin
statementNode := parentNode;
while statementNode <> nil do begin
if statementNode.instruction = AVT_FINALLY then begin
raise AVTCompilerException.create('Try block surrounded with finally block not supported in this compiler version', source, pos);
end;
statementNode := statementNode.parent;
end;
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_TRY_BEGIN);
pos := parseTry(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_FOR: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_FOR);
pos := parseFor(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_IF: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_IF);
pos := parseIf(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
AVT_DO: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_DO);
pos := parseDo(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
CHAR_CURLY_OPENED: begin
statementNode := code.appendNode(parentNode);
statementNode.setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_BLOCK);
pos := parseBlock(statementNode, code, methodRef, typeRef, source, pos + 1);
end;
CHAR_SEMICOLON: begin
code.appendNode(parentNode).setData(source.getLexemeLineIndex(pos), getPrimitiveType(AVT_VOID), AVT_BLOCK);
inc(pos);
end
else
pos := parseLocal(parentNode, code, methodRef, typeRef, source, pos);
if source.getLexemeType(pos) <> CHAR_SEMICOLON then begin
raise AVTCompilerException.create('";" expected', source, pos);
end;
inc(pos);
end;
result := pos;
end;
function AVTCodeBuilder.parseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType;
var
lxt: int;
dimensions: int;
app: AVTProgramme;
itemParsedRef: AVTItem;
typeParsedRef: AVTType;
begin
app := programme;
lxt := source.getLexemeType(pos);
if lxt = AVT_VOID then begin
source.position := pos + 1;
result := app.systemPackage.getType(AVTTypePrimitive.getName(AVT_VOID));
exit;
end;
typeParsedRef := nil;
if (lxt >= AVT_BOOLEAN) and (lxt <= AVT_DOUBLE8) then begin
typeParsedRef := app.systemPackage.getType(AVTTypePrimitive.getName(lxt));
inc(pos);
end else
if lxt = LITR_NAME then begin
itemParsedRef := resolveName(source.getLexemeAnsiString(pos), parentNode, methodRef, typeRef, pos);
if itemParsedRef is AVTPackage then begin
typeParsedRef := parseFullyQualifiedTypeName(AVTPackage(itemParsedRef), typeRef, pos + 1);
pos := source.position;
end else
if itemParsedRef is AVTType then begin
typeParsedRef := AVTType(itemParsedRef);
inc(pos);
end;
end;
if typeParsedRef = nil then begin
raise AVTCompilerException.create('Type expected', source, pos);
end;
dimensions := 0;
while (dimensions < 99) and (source.getLexemeType(pos) = CHAR_BRACKET_OPENED) and (source.getLexemeType(pos + 1) = CHAR_BRACKET_CLOSED) do begin
typeParsedRef := app.getArrayOf(typeParsedRef);
inc(dimensions);
inc(pos, 2);
end;
source.position := pos;
result := typeParsedRef;
end;
function AVTCodeBuilder.tryParseType(parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; source: AVTSource; pos: int): AVTType;
var
lxt: int;
dimensions: int;
app: AVTProgramme;
itemParsedRef: AVTItem;
typeParsedRef: AVTType;
begin
app := programme;
lxt := source.getLexemeType(pos);
if lxt = AVT_VOID then begin
source.position := pos + 1;
result := app.systemPackage.getType(AVTTypePrimitive.getName(AVT_VOID));
exit;
end;
typeParsedRef := nil;
if (lxt >= AVT_BOOLEAN) and (lxt <= AVT_DOUBLE8) then begin
typeParsedRef := app.systemPackage.getType(AVTTypePrimitive.getName(lxt));
inc(pos);
end else
if lxt = LITR_NAME then begin
itemParsedRef := resolveName(source.getLexemeAnsiString(pos), parentNode, methodRef, typeRef, pos);
if itemParsedRef is AVTPackage then begin
typeParsedRef := tryParseFullyQualifiedTypeName(AVTPackage(itemParsedRef), typeRef, pos + 1);
pos := source.position;
end else
if itemParsedRef is AVTType then begin
typeParsedRef := AVTType(itemParsedRef);
inc(pos);
end;
end;
if typeParsedRef = nil then begin
result := nil;
exit;
end;
dimensions := 0;
while (dimensions < 99) and (source.getLexemeType(pos) = CHAR_BRACKET_OPENED) and (source.getLexemeType(pos + 1) = CHAR_BRACKET_CLOSED) do begin
typeParsedRef := app.getArrayOf(typeParsedRef);
inc(dimensions);
inc(pos, 2);
end;
source.position := pos;
result := typeParsedRef;
end;
function AVTCodeBuilder.resolveName(const simpleName: AnsiString; parentNode: AVTNode; methodRef: AVTMethod; typeRef: AVTTypeStructured; pos: int): AVTItem;
var
i: int;
found: AVTItem;
childNode: AVTNode;
associate: _Object;
begin
fldResolvedVariable := nil;
repeat
for i := parentNode.length - 1 downto 0 do begin
childNode := parentNode[i];
associate := childNode.operand1;
if associate is AVTVariable then begin
if childNode.isWithVariable() then begin
found := resolveMember(AVTVariable(associate).valueType as AVTTypeStructured, simpleName, typeRef, pos);
if found <> nil then begin
fldResolvedVariable := AVTVariable(associate);
result := found;
exit;
end;
end else begin
case childNode.instruction of
DECLARE_VARIABLE, AVT_CATCH: begin
if AVTVariable(associate).simpleName = simpleName then begin
result := AVTVariable(associate);
exit;
end;
end;
end;
end;
end;
end;
parentNode := parentNode.parent;
until parentNode = nil;
found := methodRef.getArgument(simpleName);
if found <> nil then begin
result := found;
exit;
end;
found := inherited resolveName(simpleName, typeRef, pos);
if (found is AVTMember) and not found.isStatic() then begin
fldResolvedVariable := methodRef.argumentThis;
end;
result := found;
end;
function AVTCodeBuilder.insertIncrementCode(parentNode: AVTNode; code: AVTCode; typeOperandRef: AVTTypePrimitive; isIncrement: boolean; lineIndex: int): AVTNode;
var
currentNode: AVTNode;
newConstant: AVTConstant;
typeIntRef: AVTTypePrimitive;
begin
case typeOperandRef.primitiveKind of
AVT_REAL: begin
newConstant := AVTConstant.create(typeOperandRef);
if isIncrement then begin
newConstant.value.asReal := 1.0;
end else begin
newConstant.value.asReal := -1.0;
end;
currentNode := code.appendNode(parentNode, lineIndex, typeOperandRef, OPER_SCAL_ADD, typeOperandRef);
code.appendNode(currentNode).setData(lineIndex, typeOperandRef, LOAD_CONST, newConstant);
end;
AVT_CHAR: begin
typeIntRef := getPrimitiveType(AVT_INT);
newConstant := AVTConstant.create(typeIntRef);
if isIncrement then begin
newConstant.value.asInt := 1;
end else begin
newConstant.value.asInt := -1;
end;
currentNode := code.appendNode(parentNode, lineIndex, typeOperandRef, OPER_TYPE_CAST, typeOperandRef, typeIntRef);
currentNode := code.appendNode(currentNode, lineIndex, typeIntRef, OPER_SCAL_ADD, typeIntRef);
code.appendNode(currentNode).setData(lineIndex, typeIntRef, LOAD_CONST, newConstant);
end
else
newConstant := AVTConstant.create(getPrimitiveType(AVT_BYTE));
if isIncrement then begin
newConstant.value.asByte := 1;
end else begin
newConstant.value.asByte := -1;
end;
cast(newConstant, newConstant, typeOperandRef);
currentNode := code.appendNode(parentNode, lineIndex, typeOperandRef, OPER_VECT_ADD, typeOperandRef);
code.appendNode(currentNode).setData(lineIndex, typeOperandRef, LOAD_CONST, newConstant);
end;
result := currentNode;
end;
function AVTCodeBuilder.cast(currentNode: AVTNode; code: AVTCode; typeNewRef: AVTType): AVTNode;
var
associate: _Object;
typeOldRef: AVTType;
convertNode: AVTNode;
begin
typeOldRef := currentNode.dataType;
if typeOldRef = typeNewRef then begin
result := currentNode;
exit;
end;
if typeOldRef = nil then begin
if typeNewRef is AVTTypeStructured then begin
currentNode.dataType := typeNewRef;
result := currentNode;
exit;
end;
end else
if typeOldRef is AVTTypePrimitive then begin
if typeNewRef is AVTTypePrimitive then begin
associate := currentNode.operand1;
if (currentNode.instruction = LOAD_CONST) and (associate is AVTConstant) then begin
cast(AVTConstant(associate), AVTConstant(associate), AVTTypePrimitive(typeNewRef));
currentNode.dataType := typeNewRef;
result := currentNode;
exit;
end;
if (AVTTypePrimitive(typeNewRef).primitiveKind = AVT_INT) and not typeOldRef.isStackable() then begin
currentNode.dataType := typeNewRef;
result := currentNode;
exit;
end;
convertNode := code.insertNode(currentNode.parent, currentNode.index, currentNode.lineIndex, typeNewRef, OPER_TYPE_CAST, typeNewRef, typeOldRef);
code.moveNode(currentNode, convertNode, 0);
result := convertNode;
exit;
end;
end else
if typeOldRef is AVTTypeStructured then begin
if typeNewRef is AVTTypeStructured then begin
if typeNewRef.isAssignableFrom(typeOldRef) then begin
currentNode.dataType := typeNewRef;
result := currentNode;
exit;
end;
convertNode := code.insertNode(currentNode.parent, currentNode.index, currentNode.lineIndex, typeNewRef, OPER_TYPE_CAST, typeNewRef, typeOldRef);
code.moveNode(currentNode, convertNode, 0);
result := convertNode;
exit;
end;
end;
result := currentNode;
end;
function AVTCodeBuilder.getPrimitiveTypeForIntValue(value: int): AVTTypePrimitive;
begin
if (value >= -$80) and (value < $80) then begin
result := getPrimitiveType(AVT_BYTE);
exit;
end;
if (value >= -$8000) and (value < $8000) then begin
result := getPrimitiveType(AVT_SHORT);
exit;
end;
result := getPrimitiveType(AVT_INT);
end;
procedure AVTCodeBuilder.parseMethods(typeRef: AVTTypeStructured);
var
member: TObject;
begin
with typeRef.members() do while hasMoreElements() do begin
member := nextElement().objectValue();
if member is AVTMethod then buildCode(AVTMethod(member));
end;
end;
function AVTCodeBuilder.getThrowableType(): AVTTypeStructured;
var
packageAvtLangRef: AVTPackage;
typeThrowableRef: AVTTypeStructured;
begin
typeThrowableRef := fldTypeThrowableRef;
if typeThrowableRef <> nil then begin
result := typeThrowableRef;
exit;
end;
packageAvtLangRef := programme.getPackage('avt.lang');
if packageAvtLangRef = nil then begin
result := nil;
exit;
end;
typeThrowableRef := packageAvtLangRef.getType('Throwable') as AVTTypeStructured;
fldTypeThrowableRef := typeThrowableRef;
result := typeThrowableRef;
end;
function AVTCodeBuilder.getStructType(): AVTTypeStructured;
var
packageAvtLangRef: AVTPackage;
typeStructRef: AVTTypeStructured;
begin
typeStructRef := fldTypeStructRef;
if typeStructRef <> nil then begin
result := typeStructRef;
exit;
end;
packageAvtLangRef := programme.getPackage('avt.lang');
if packageAvtLangRef = nil then begin
result := nil;
exit;
end;
typeStructRef := packageAvtLangRef.getType('Struct') as AVTTypeStructured;
fldTypeStructRef := typeStructRef;
result := typeStructRef;
end;
function AVTCodeBuilder.getObjectType(): AVTTypeStructured;
var
packageAvtLangRef: AVTPackage;
typeObjectRef: AVTTypeStructured;
begin
typeObjectRef := fldTypeObjectRef;
if typeObjectRef <> nil then begin
result := typeObjectRef;
exit;
end;
packageAvtLangRef := programme.getPackage('avt.lang');
if packageAvtLangRef = nil then begin
result := nil;
exit;
end;
typeObjectRef := packageAvtLangRef.getType('Object') as AVTTypeStructured;
fldTypeObjectRef := typeObjectRef;
result := typeObjectRef;
end;
{%endregion}
end.