/*
Компилятор языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package ru.malik.elaborarer.avtoo.lang;
import avt.lang.array.*;
import avt.util.*;
public abstract class Callable(OverriddableMember, Cloneable, Measureable, ObjectArray, TypedItem, TypedMember, AVTOOConstants)
{
private int fldVirtualIndex;
private int fldServiceIndex;
private final Local[] fldArgumentsStore;
private final ArgumentArray fldArgumentsArray;
private final Hashtable fldArgumentsTable;
private final Local fldThisArgument;
private final Code fldCode;
protected (ClassType parentType, int attributes, Type type, String specialSimpleName, Local[] arguments, int declarationPosition, int documentationPosition):
super(parentType, attributes, type, specialSimpleName, declarationPosition, documentationPosition) {
int length = arguments == null ? 0 : arguments.length;
Local[] otherArguments = new Local[length];
Array.copy(arguments, 0, otherArguments, 0, length);
if(Array.indexOf(null, otherArguments, 0, 0) >= 0)
{
throw new NullPointerException(String.format(avt.lang.package.getResourceString("null-pointer.argument.component"), new Object[] { "arguments" }));
}
for(Local argument = length <= 0 ? null : otherArguments[0], int index = 1; index < length; argument = otherArguments[index++]) if(Array.indexOf(argument, otherArguments, index, 0) >= 0)
{
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument.component.two-ones-is-equal"), new Object[] { "arguments" }));
}
for(int index = length; index-- > 0; ) if(otherArguments[index].type == null)
{
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument.component.uninitialized-property"), new Object[] { "arguments", "type" }));
}
Local thisArgument = (attributes & ATTR_STATIC) != 0 || parentType == null ? null : parentType.thisArgument;
Hashtable table = thisArgument == null && length <= 0 ? null : new Hashtable();
for(int index = length; index-- > 0; )
{
Local argument = otherArguments[index];
String name = argument.specialSimpleName;
if(name != null) table[name] = argument;
}
if(thisArgument != null)
{
String name = thisArgument.specialSimpleName;
if(name != null) table[name] = thisArgument;
}
fldVirtualIndex = -1;
fldServiceIndex = -1;
fldArgumentsStore = otherArguments;
fldArgumentsArray = new ArgumentArray(thisArgument, otherArguments);
fldArgumentsTable = table;
fldThisArgument = thisArgument;
fldCode = (attributes & (ATTR_ABSTRACT | ATTR_NATIVE)) != 0 ? null : createCode();
}
public boolean isOverrides(OverriddableMember anot) { return super.isOverrides(anot) && isIdentityArguments(((Callable) anot).fldArgumentsStore); }
public boolean canThrown() { return false; }
public boolean canThrown(ClassType throwable) { return throwable != null && throwable.isFreeThrowableType(); }
public final boolean isNative() { return (attributes & ATTR_NATIVE) != 0; }
public final boolean isInterrupt() { return (attributes & ATTR_INTERRUPT) != 0; }
public final boolean isSynchronized() { return (attributes & ATTR_SYNCHRONIZED) != 0; }
public final boolean isArgument(Local argument) { return argument != null && (argument == fldThisArgument || Array.indexOf(argument, fldArgumentsStore, 0, 0) >= 0); }
public final boolean isIdentityArguments(Callable member) { return member != null && isIdentityArguments(member.fldArgumentsStore); }
public final boolean isIdentityArguments(Type[] arguments) {
int length = arguments == null ? 0 : arguments.length;
Local[] store = fldArgumentsStore;
if(length != store.length)
{
return false;
}
for(int index = 0; index < length; index++)
{
if(arguments[index] != store[index].type) return false;
}
return true;
}
public final boolean isIdentityArguments(TypedItem[] arguments) {
int length = arguments == null ? 0 : arguments.length;
Local[] store = fldArgumentsStore;
if(length != store.length)
{
return false;
}
for(int index = 0; index < length; index++)
{
TypedItem argument = arguments[index];
if(argument == null || argument.type != store[index].type) return false;
}
return true;
}
public final boolean isAssignableArguments(Type[] arguments) {
int length = arguments == null ? 0 : arguments.length;
Local[] store = fldArgumentsStore;
if(length != store.length)
{
return false;
}
for(int index = 0; index < length; index++)
{
Type type = arguments[index];
if(type == null || !store[index].type.isAssignableFrom(type)) return false;
}
return true;
}
public final boolean isConvertableArguments(Type[] arguments) {
int length = arguments == null ? 0 : arguments.length;
Local[] store = fldArgumentsStore;
if(length != store.length)
{
return false;
}
for(int index = 0; index < length; index++)
{
Type type = arguments[index];
if(type == null || !store[index].type.isConvertableFrom(type)) return false;
}
return true;
}
public final Local getArgument(String specialSimpleName) {
if(specialSimpleName == null) return null;
Hashtable table = fldArgumentsTable;
return table == null ? null : (Local) table[specialSimpleName];
}
public final int virtualIndex { read = fldVirtualIndex }
public final int serviceIndex { read = fldServiceIndex }
public final ArgumentArray arguments { read = fldArgumentsArray }
public final Code code { read = fldCode }
protected abstract String composeFasmSimpleName();
protected String composeFasmFullName() {
ClassType enclosing = parentType;
return (new StringBuilder() + (enclosing != null ? enclosing.fasmFullName : "") + '$' + fasmSimpleName + fldArgumentsArray.toFasmString()).toString();
}
package final void setVirtualIndex(int virtualIndex) { fldVirtualIndex = virtualIndex; }
package final void setServiceIndex(int serviceIndex) { fldServiceIndex = serviceIndex; }
private Code createCode() {
Programme programme = parentProgramme;
Code result = programme == null ? null : programme.newCode(this);
if(result == null) result = new Code(this);
return result;
}
}