use of dyvilx.tools.compiler.ast.parameter.ParameterList in project Dyvil by Dyvil.
the class Annotation method resolve.
@Override
public void resolve(MarkerList markers, IContext context) {
this.arguments.resolve(markers, context);
final IClass theClass;
if (this.type == null || (theClass = this.type.getTheClass()) == null) {
return;
}
final ParameterList parameterList = theClass.getParameters();
for (int i = 0, count = parameterList.size(); i < count; i++) {
final IParameter parameter = parameterList.get(i);
final IType parameterType = parameter.getType();
final IValue value = this.arguments.get(parameter);
if (value == null) {
if (parameter.getValue() == null) {
markers.add(Markers.semanticError(this.getPosition(), "annotation.parameter.missing", this.type, parameter.getName()));
}
continue;
}
IValue typedValue = value.withType(parameterType, parameterType, markers, context);
if (typedValue == null) {
markers.add(TypeChecker.typeError(value, parameterType, parameterType, "annotation.parameter.type", parameter.getName()));
continue;
}
typedValue = IValue.toAnnotationConstant(typedValue, markers, context);
if (typedValue != value) {
this.arguments.set(i, parameter.getLabel(), typedValue);
}
}
}
use of dyvilx.tools.compiler.ast.parameter.ParameterList in project Dyvil by Dyvil.
the class Annotation method write.
public void write(AnnotationVisitor writer) {
final IClass iclass = this.type.getTheClass();
final ParameterList parameterList = iclass.getParameters();
for (int i = 0, count = parameterList.size(); i < count; i++) {
final IParameter parameter = parameterList.get(i);
final IValue argument = this.arguments.get(parameter);
if (argument != null) {
argument.writeAnnotationValue(writer, parameter.getName().qualified);
}
}
writer.visitEnd();
}
use of dyvilx.tools.compiler.ast.parameter.ParameterList in project Dyvil by Dyvil.
the class AbstractMethod method checkImplicitMatch.
@Override
public void checkImplicitMatch(MatchList<IMethod> list, IValue value, IType type) {
if (!this.isImplicitConversion()) {
// The method has to be 'implicit static'
return;
}
final ParameterList parameterList = this.getParameters();
if (parameterList.size() != 1) {
// and only take exactly one parameter
return;
}
if (type != null && !Types.isSuperType(type, this.getType().asParameterType())) {
// The method's return type has to be a sub-type of the target type
return;
}
final IType parType = parameterList.get(0).getCovariantType();
// Note: this explicitly uses null as the context parameter to avoid nested implicit conversions
final int match = TypeChecker.getTypeMatch(value, parType, null);
// >= to allow the "light" conversions that are built in based on type, e.g. primitive widening or (un)boxing
if (match >= IValue.CONVERSION_MATCH) {
list.add(new Candidate<>(this, match, parType, false));
}
}
use of dyvilx.tools.compiler.ast.parameter.ParameterList in project Dyvil by Dyvil.
the class AbstractMethod method checkMatch.
@Override
public void checkMatch(MatchList<IMethod> list, IValue receiver, Name name, ArgumentList arguments) {
if (name != this.name && name != null) {
return;
}
final ParameterList parameters = this.getParameters();
final int parameterStartIndex;
final int argumentStartIndex;
final int argumentCount;
final int parameterCount = parameters.size();
final int[] matchValues;
final IType[] matchTypes;
boolean invalid = false;
final int mod = this.attributes.flags() & Modifiers.INFIX;
if (receiver == null) {
if (mod == Modifiers.INFIX) {
// disallow non-qualified access to infix methods
invalid = true;
}
if (arguments == null) {
list.add(new Candidate<>(this));
return;
}
argumentCount = arguments.size();
matchValues = new int[argumentCount];
matchTypes = new IType[argumentCount];
argumentStartIndex = 0;
parameterStartIndex = 0;
} else if (mod != 0 && receiver.isClassAccess()) {
// Static access to static method
final IType receiverType = receiver.getType();
if (!Types.isSuperType(this.getReceiverType(), receiverType)) {
// Disallow access from the wrong type
return;
}
if (arguments == null) {
list.add(new Candidate<>(this, IValue.EXACT_MATCH, receiverType, false));
return;
}
parameterStartIndex = 0;
argumentCount = arguments.size();
argumentStartIndex = 1;
matchValues = new int[1 + argumentCount];
matchTypes = new IType[1 + argumentCount];
matchValues[0] = 1;
matchTypes[0] = receiverType;
} else {
if (// a
mod == Modifiers.STATIC && !receiver.isClassAccess() || // b
mod == 0 && receiver.isClassAccess() && !receiver.getType().getTheClass().isObject()) {
// Disallow non-static access to static method (a)
// and static access to instance method (unless it's an object class) (b)
invalid = true;
}
final IType receiverType;
if (mod == Modifiers.INFIX && !parameters.isEmpty()) {
// Infix access to infix method
receiverType = parameters.get(0).getCovariantType();
parameterStartIndex = 1;
} else {
// Infix access to instance method
receiverType = this.getReceiverType();
parameterStartIndex = 0;
}
final int receiverMatch = TypeChecker.getTypeMatch(receiver, receiverType, list);
if (receiverMatch == IValue.MISMATCH) {
return;
}
if (arguments == null) {
list.add(new Candidate<>(this, receiverMatch, receiverType, invalid));
return;
}
argumentCount = arguments.size();
argumentStartIndex = 1;
matchValues = new int[1 + argumentCount];
matchTypes = new IType[1 + argumentCount];
matchValues[0] = receiverMatch;
matchTypes[0] = receiverType;
}
final int parametersLeft = parameterCount - parameterStartIndex;
if (argumentCount > parametersLeft && !this.isVariadic()) {
return;
}
int defaults = 0;
int varargs = 0;
for (int argumentIndex = 0; argumentIndex < parametersLeft; argumentIndex++) {
final IParameter parameter = parameters.get(parameterStartIndex + argumentIndex);
final int partialVarargs = arguments.checkMatch(matchValues, matchTypes, argumentStartIndex, argumentIndex, parameter, list);
switch(partialVarargs) {
case ArgumentList.MISMATCH:
return;
case ArgumentList.DEFAULT:
defaults++;
continue;
default:
varargs += partialVarargs;
}
}
for (int matchValue : matchValues) {
if (matchValue == IValue.MISMATCH) {
// Mismatch
return;
}
}
list.add(new Candidate<>(this, matchValues, matchTypes, defaults, varargs, invalid));
}
use of dyvilx.tools.compiler.ast.parameter.ParameterList in project Dyvil by Dyvil.
the class CodeMethod method filterOverride.
private boolean filterOverride(IMethod candidate, MarkerList markers, ITypeContext typeContext) {
final String candidateInternalName = candidate.getInternalName();
final boolean sameName = this.name == candidate.getName();
final boolean sameInternalName = this.getInternalName().equals(candidateInternalName);
if (// same name but different internal name
sameName && !sameInternalName) {
if (this.name.qualified.equals(this.internalName)) // no AutoMangled or BytecodeName annotation, otherwise the user probably knows what they are doing and
// doesn't need a warning
{
final Marker marker = Markers.semantic(this.position, "method.override.mangled_mismatch", this.name, candidateInternalName);
marker.addInfo(Markers.getSemantic("method.override.mangled_mismatch.info", candidateInternalName));
markers.add(marker);
}
return true;
}
if (!sameName && sameInternalName) {
final Marker marker = Markers.semanticError(this.position, "method.override.mangled_clash", this.name, candidate.getName(), candidateInternalName);
marker.addInfo(Markers.getSemantic("method.override.mangled_clash.info"));
// hard error so it doesn't matter if we remove or not - bytecode will never be generated
return true;
}
// sameName && sameInternalName should be true
final IClass enclosingClass = candidate.getEnclosingClass();
boolean errors = true;
for (IMethod method : this.overrideMethods) {
if (method != candidate && method.getEnclosingClass() == enclosingClass) {
// If this method overrides two methods from the same class, we do not produce any parameter label errors
errors = false;
}
}
final ParameterList params = candidate.getParameters();
for (int i = 0, count = params.size(); i < count; i++) {
final IParameter thisParam = this.parameters.get(i);
final Name thisName = thisParam.getLabel();
final Name otherName = params.get(i).getLabel();
if (thisName == otherName || thisName == null || otherName == null) {
// Parameter labels match
continue;
}
if (errors) {
final Marker marker = Markers.semantic(thisParam.getPosition(), "method.override.parameter_label", i + 1, thisName, otherName);
addOverrideInfo(typeContext, candidate, marker);
markers.add(marker);
}
// This method does not properly override the candidate
return true;
}
return false;
}
Aggregations