use of dyvil.source.position.SourcePosition 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 dyvil.source.position.SourcePosition in project Dyvil by Dyvil.
the class OptionalChainAware method nullCoalescing.
static IValue nullCoalescing(IValue lhs, IValue rhs) {
BindingIfStatement bindingIf;
if (lhs instanceof BindingIfStatement && (bindingIf = (BindingIfStatement) lhs).getElse() == NullValue.NULL) {
// safe bet that the rhs used to be an optional chain
// this branch is actually an optimization and technically not necessary, but it is very common
// to use the null coalescing operator after an optional chain.
final IValue then = bindingIf.getThen();
if (NullableType.isNullable(then.getType())) {
// Perform the following transformation:
// if let $0 = oldReceiver { $0.oldAccess } else null
// becomes
// if (let $0 = oldReceiver, let $1 = $0.oldAccess) { $1 } else { <rhs> }
final Variable var = newVar(bindingIf.getPosition(), then);
bindingIf.addVariable(var);
bindingIf.setThen(new FieldAccess(var));
}
// if the then branch of the old binding if is not nullable, we simply set the rhs
bindingIf.setElse(rhs);
return bindingIf;
}
// the lhs was not an optional chain, so we set up an impromptu null coalescing inline implementation
final SourcePosition position = lhs.getPosition();
// let l = <lhs>
final Variable var = newVar(position, lhs);
// if let l = <lhs> { l } else { <rhs> }
bindingIf = new BindingIfStatement(position);
bindingIf.addVariable(var);
bindingIf.setThen(new FieldAccess(var));
bindingIf.setElse(rhs);
return bindingIf;
}
use of dyvil.source.position.SourcePosition in project Dyvil by Dyvil.
the class ICall method toLambda.
default IValue toLambda(MarkerList markers, IContext context, int wildcards) {
SourcePosition position = this.getPosition();
final IParameter[] parameters = new IParameter[wildcards];
for (int i = 0; i < wildcards; i++) {
parameters[i] = new CodeParameter(null, position, Name.fromRaw("wildcard$" + i), Types.UNKNOWN, new AttributeList());
}
int parIndex = 0;
final IValue receiver = this.getReceiver();
if (receiver != null && receiver.isPartialWildcard()) {
this.setReceiver(receiver.withLambdaParameter(parameters[parIndex++]));
}
final ArgumentList arguments = this.getArguments();
for (int i = 0, size = arguments.size(); i < size; i++) {
final IValue argument = arguments.get(i, null);
if (argument.isPartialWildcard()) {
arguments.set(i, null, argument.withLambdaParameter(parameters[parIndex++]));
}
}
final LambdaExpr lambdaExpr = new LambdaExpr(position, parameters, wildcards);
lambdaExpr.setImplicitParameters(true);
lambdaExpr.setValue(this);
return lambdaExpr.resolve(markers, context);
}
use of dyvil.source.position.SourcePosition in project Dyvil by Dyvil.
the class ProcessedText method resolve.
@Override
public IValue resolve(MarkerList markers, IContext context) {
final int startLine = this.position.startLine();
final int startColumn = this.position.startColumn();
final StringInterpolationExpr parts = new StringInterpolationExpr();
final String text = this.text;
final int length = text.length();
int prev = 0;
for (int startIndex = 0; startIndex < length; ) {
final int c = text.codePointAt(startIndex);
// advance to an identifier character
if (!Character.isJavaIdentifierStart(c)) {
startIndex += Character.charCount(c);
continue;
}
final int endIndex = identifierEnd(text, startIndex + 1, length);
final String key = text.substring(startIndex, endIndex);
final IDataMember field = context.resolveField(Name.fromRaw(key));
if (field != null && (field.isLocal() || field.hasModifier(Modifiers.PUBLIC))) {
// append contents before this identifier
parts.append(new StringValue(text.substring(prev, startIndex)));
final SourcePosition position = SourcePosition.apply(startLine, startColumn + startIndex, startColumn + endIndex);
parts.append(new FieldAccess(position, null, field));
// advance to the end of the identifier
prev = endIndex;
startIndex = endIndex;
continue;
}
startIndex += Character.charCount(c);
}
if (prev != length) {
parts.append(new StringValue(text.substring(prev, length)));
}
return new WriteCall(parts.resolve(markers, context));
}
use of dyvil.source.position.SourcePosition in project Dyvil by Dyvil.
the class CaseClassMetadata method createUnapplyMethod.
private CodeMethod createUnapplyMethod() {
// static final func unapply<TypeParams...>(value: This) -> (T...)
final SourcePosition position = this.theClass.position();
final AttributeList attributes = AttributeList.of(Modifiers.PUBLIC | Modifiers.STATIC_FINAL | Modifiers.GENERATED);
final IType type = this.getUnapplyReturnType();
final CodeMethod unapply = new CodeMethod(this.theClass, Names.unapply, type, attributes);
unapply.setPosition(position);
unapply.getTypeParameters().addAll(this.theClass.getTypeParameters());
final CodeParameter parameter = new CodeParameter(unapply, position, Names.value, this.theClass.getThisType());
unapply.getParameters().add(parameter);
// = (value.classParams...)
final TupleExpr tupleExpr = new TupleExpr(position);
final ArgumentList arguments = tupleExpr.getValues();
for (IParameter param : this.theClass.getParameters()) {
// value
final FieldAccess thisAccess = new FieldAccess(position, null, parameter);
// value.classParam
final IValue fieldAccess;
if (param.isOverride()) {
// if the class parameter is marked as 'override', we have to resolve it from a super-class
// the easiest way to do this is by name
fieldAccess = new FieldAccess(position, thisAccess, param.getName());
} else {
fieldAccess = new FieldAccess(position, thisAccess, param);
}
arguments.add(fieldAccess);
}
unapply.setValue(tupleExpr);
return unapply;
}
Aggregations