use of dyvilx.tools.compiler.ast.expression.ThisExpr in project Dyvil by Dyvil.
the class Field method resolve.
@Override
public void resolve(MarkerList markers, IContext context) {
super.resolve(markers, context);
if (this.value != null) {
final IContext context1 = new CombiningContext(this, context);
this.value = this.value.resolve(markers, context1);
boolean inferType = false;
if (this.type == Types.UNKNOWN) {
inferType = true;
this.type = this.value.getType();
}
final TypeChecker.MarkerSupplier markerSupplier = TypeChecker.markerSupplier("field.type.incompatible", "field.type", "value.type", this.name);
this.value = TypeChecker.convertValue(this.value, this.type, this.type, markers, context1, markerSupplier);
if (inferType) {
this.type = this.value.getType();
if (this.type == Types.UNKNOWN && this.value.isResolved()) {
markers.add(Markers.semantic(this.position, "field.type.infer", this.name.unqualified));
this.type = Types.ANY;
}
}
} else if (this.type == Types.UNKNOWN) {
markers.add(Markers.semantic(this.position, "field.type.infer.novalue", this.name.unqualified));
this.type = Types.ANY;
}
if (this.property == null) {
return;
}
this.property.setType(this.type);
final IMethod getter = this.property.getGetter();
final IMethod setter = this.property.getSetter();
final IValue receiver = this.hasModifier(Modifiers.STATIC) ? null : new ThisExpr(this.enclosingClass.getThisType(), VariableThis.DEFAULT);
if (getter != null) {
getter.setType(this.type);
if (getter.getValue() == null) {
// get: this.FIELD_NAME
getter.setValue(new FieldAccess(getter.getPosition(), receiver, this));
}
}
if (setter != null) {
final IParameter setterParameter = setter.getParameters().get(0);
setterParameter.setType(this.type);
if (setter.getValue() == null) {
final SourcePosition setterPosition = setter.getPosition();
if (this.hasModifier(Modifiers.FINAL)) {
markers.add(Markers.semanticError(setterPosition, "field.property.setter.final", this.name));
// avoid abstract method error
setter.setValue(new VoidValue(setterPosition));
} else {
// set: this.FIELD_NAME = newValue
setter.setValue(new FieldAssignment(setterPosition, receiver, this, new FieldAccess(setterPosition, null, setterParameter)));
}
}
}
this.property.resolve(markers, context);
}
use of dyvilx.tools.compiler.ast.expression.ThisExpr in project Dyvil by Dyvil.
the class ThisSuperParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case THIS_SUPER:
switch(type) {
case DyvilKeywords.THIS:
this.mode = TYPE;
this.value = new ThisExpr(token.raw());
return;
case DyvilKeywords.SUPER:
this.mode = TYPE;
this.value = new SuperExpr(token.raw());
return;
}
pm.popParser(true);
return;
case TYPE:
if (ExpressionParser.isGenericCall(token, type)) {
this.mode = TYPE_END;
pm.splitJump(token, 1);
pm.pushParser(new TypeParser(this.value, true));
return;
}
this.valueConsumer.setValue(this.value);
pm.popParser(true);
return;
case TYPE_END:
pm.popParser();
this.valueConsumer.setValue(this.value);
if (!TypeParser.isGenericEnd(token, type)) {
pm.reparse();
pm.report(token, this.value.valueTag() == IValue.SUPER ? "super.close_angle" : "this.close_angle");
return;
}
pm.splitJump(token, 1);
}
}
use of dyvilx.tools.compiler.ast.expression.ThisExpr in project Dyvil by Dyvil.
the class ClassMetadata method createDefaultConstructor.
private CodeConstructor createDefaultConstructor() {
// init(classParams...)
final SourcePosition position = this.theClass.position();
final AttributeList attributes = this.theClass.getConstructorAttributes();
attributes.addFlag(Modifiers.GENERATED);
final CodeConstructor constructor = new CodeConstructor(this.theClass, attributes);
constructor.setPosition(position);
this.copyClassParameters(constructor);
// : super(superParams...)
final IType superType = this.theClass.getSuperType();
if (superType != null) {
// Generate the constructor body
ArgumentList arguments = this.theClass.getSuperConstructorArguments();
if (arguments == null) {
arguments = ArgumentList.empty();
}
final InitializerCall init = new InitializerCall(this.theClass.getPosition(), true, arguments, superType);
constructor.setInitializer(init);
}
// { this.classParams... = classParams... }
final ParameterList classParams = this.theClass.getParameters();
final StatementList ctorBody = new StatementList();
final ParameterList ctorParams = constructor.getParameters();
// j is the counter for class parameters, as there may be leading synthetic constructor parameters
for (int i = 0, j = 0, count = ctorParams.size(); i < count; i++) {
final IParameter ctorParam = ctorParams.get(i);
if (ctorParam.hasModifier(Modifiers.SYNTHETIC)) {
continue;
}
final IParameter classParam = classParams.get(j++);
if (classParam.hasModifier(Modifiers.OVERRIDE)) {
continue;
}
final IValue receiver = new ThisExpr(this.theClass);
final FieldAccess access = new FieldAccess(ctorParam);
final FieldAssignment assignment = new FieldAssignment(position, receiver, classParam, access);
ctorBody.add(assignment);
}
constructor.setValue(ctorBody);
return constructor;
}
use of dyvilx.tools.compiler.ast.expression.ThisExpr in project Dyvil by Dyvil.
the class AbstractMethod method checkArguments.
@Override
public IValue checkArguments(MarkerList markers, SourcePosition position, IContext context, IValue receiver, ArgumentList arguments, GenericData genericData) {
final ParameterList parameters = this.getParameters();
if (receiver != null) {
final int mod = this.attributes.flags() & Modifiers.INFIX;
if (mod == Modifiers.INFIX && !receiver.isClassAccess() && !parameters.isEmpty()) {
// infix or extension method, declaring class implicit
final IParameter parameter = parameters.get(0);
final IType paramType = parameter.getCovariantType();
updateReceiverType(receiver, genericData);
receiver = TypeChecker.convertValue(receiver, paramType, genericData, markers, context, TypeChecker.markerSupplier("method.access.infix_type", this.name));
updateReceiverType(receiver, genericData);
for (int i = 1, count = parameters.size(); i < count; i++) {
arguments.checkValue(i - 1, parameters.get(i), genericData, position, markers, context);
}
if (genericData != null) {
this.checkTypeVarsInferred(markers, position, genericData);
}
return receiver;
}
updateReceiverType(receiver, genericData);
if ((mod & Modifiers.STATIC) != 0) {
if (!receiver.isClassAccess()) {
// static method called like instance method -> warning
markers.add(Markers.semanticError(position, "method.access.static", this.name));
} else if (this.getReceiverType().getTheClass() == this.enclosingClass && receiver.getType().getTheClass() != this.enclosingClass) {
// static method called on wrong type -> warning
markers.add(Markers.semantic(position, "method.access.static.type", this.name, this.enclosingClass.getFullName()));
}
receiver = receiver.asIgnoredClassAccess();
} else if (receiver.isClassAccess()) {
if (!receiver.getType().getTheClass().isObject()) {
// declaring class is not an object class -> error
markers.add(Markers.semanticError(position, "method.access.instance", this.name));
}
} else {
// normal instance method access
receiver = TypeChecker.convertValue(receiver, this.getReceiverType(), receiver.getType(), markers, context, TypeChecker.markerSupplier("method.access.receiver_type", this.name));
}
if (receiver != null) {
updateReceiverType(receiver, genericData);
}
} else if (!this.isStatic()) {
if (!context.isThisAvailable()) {
// called from static context -> error
markers.add(Markers.semantic(position, "method.access.instance", this.name));
} else {
// unqualified call
final IType receiverType = this.enclosingClass.getThisType();
receiver = new ThisExpr(position, receiverType, markers, context);
if (genericData != null) {
genericData.setFallbackTypeContext(receiverType);
}
if (!this.isNested() && !this.enclosingClass.isAnonymous()) {
markers.add(Markers.semantic(position, "method.access.unqualified", this.name.unqualified));
}
}
}
for (int i = 0, count = parameters.size(); i < count; i++) {
arguments.checkValue(i, parameters.get(i), genericData, position, markers, context);
}
if (genericData != null) {
this.checkTypeVarsInferred(markers, position, genericData);
}
return receiver;
}
Aggregations