use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.
the class ColonOperator method getTypeMatch.
@Override
public int getTypeMatch(IType type, IImplicitContext implicitContext) {
if (!Types.isSuperClass(type, TupleType.getTupleClass(2).getClassType())) {
if (type.getAnnotation(LazyFields.COLON_CONVERTIBLE) != null) {
return CONVERSION_MATCH;
}
return MISMATCH;
}
final IType leftType = Types.resolveTypeSafely(type, LazyFields.KEY_PARAMETER);
final int leftMatch = TypeChecker.getTypeMatch(this.left, leftType, implicitContext);
if (leftMatch == MISMATCH) {
return MISMATCH;
}
final IType rightType = Types.resolveTypeSafely(type, LazyFields.VALUE_PARAMETER);
final int rightMatch = TypeChecker.getTypeMatch(this.right, rightType, implicitContext);
if (rightMatch == MISMATCH) {
return MISMATCH;
}
return Math.min(leftMatch, rightMatch);
}
use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.
the class AttributeList method getAnnotation.
public Annotation getAnnotation(IClass type) {
for (int i = 0; i < this.size; i++) {
final Attribute attribute = this.data[i];
final IType attributeType = attribute.getType();
if (attributeType != null && attributeType.getTheClass() == type) {
return (Annotation) attribute;
}
}
return null;
}
use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.
the class AbstractConstructor method checkArguments.
@Override
public IType checkArguments(MarkerList markers, SourcePosition position, IContext context, IType type, ArgumentList arguments) {
final IClass theClass = this.enclosingClass;
if (!theClass.isTypeParametric()) {
for (int i = 0, count = this.parameters.size(); i < count; i++) {
arguments.checkValue(i, this.parameters.get(i), null, position, markers, context);
}
return type;
}
final IType classType = theClass.getThisType();
final GenericData genericData = new GenericData(theClass);
classType.inferTypes(type, genericData);
genericData.lockAvailable();
// Check Values and infer Types
for (int i = 0, count = this.parameters.size(); i < count; i++) {
arguments.checkValue(i, this.parameters.get(i), genericData, position, markers, context);
}
genericData.lockAvailable();
// Check Type Var Inference and Compatibility
final TypeParameterList typeParams = theClass.getTypeParameters();
for (int i = 0, count = typeParams.size(); i < count; i++) {
final ITypeParameter typeParameter = typeParams.get(i);
final IType typeArgument = genericData.resolveType(typeParameter);
if (typeArgument == null) {
final IType inferredType = typeParameter.getUpperBound();
markers.add(Markers.semantic(position, "constructor.typevar.infer", theClass.getName(), typeParameter.getName(), inferredType));
genericData.addMapping(typeParameter, inferredType);
} else if (!typeParameter.isAssignableFrom(typeArgument, genericData)) {
final Marker marker = Markers.semanticError(position, "constructor.typevar.incompatible", theClass.getName(), typeParameter.getName());
marker.addInfo(Markers.getSemantic("type.generic.argument", typeArgument));
marker.addInfo(Markers.getSemantic("type_parameter.declaration", typeParameter));
markers.add(marker);
}
}
return classType.getConcreteType(genericData);
}
use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.
the class RangeForStatement method writeStatement.
@Override
public void writeStatement(MethodWriter writer) throws BytecodeException {
// Determine the kind (int, long, float, double, Rangeable) of the range to fasten up compilation.
byte kind = RANGEABLE;
boolean boxed = false;
final int lineNumber = this.lineNumber();
final IVariable var = this.variable;
final IType varType = var.getType();
final MethodCall rangeOperator = (MethodCall) var.getValue();
final IValue startValue = getStartValue(rangeOperator);
final IValue endValue = getEndValue(rangeOperator);
final IType elementType = this.elementType;
final boolean halfOpen = isHalfOpen(rangeOperator);
if (elementType.isPrimitive()) {
switch(elementType.getTypecode()) {
case PrimitiveType.BYTE_CODE:
case PrimitiveType.SHORT_CODE:
case PrimitiveType.CHAR_CODE:
case PrimitiveType.INT_CODE:
kind = INT;
break;
case PrimitiveType.LONG_CODE:
kind = LONG;
break;
case PrimitiveType.FLOAT_CODE:
kind = FLOAT;
break;
case PrimitiveType.DOUBLE_CODE:
kind = DOUBLE;
break;
}
if (!varType.isPrimitive()) {
boxed = true;
}
}
dyvilx.tools.asm.Label startLabel = this.startLabel.getTarget();
dyvilx.tools.asm.Label updateLabel = this.updateLabel.getTarget();
dyvilx.tools.asm.Label endLabel = this.endLabel.getTarget();
dyvilx.tools.asm.Label scopeLabel = new dyvilx.tools.asm.Label();
writer.visitLabel(scopeLabel);
// Write the start value and store it in the variable.
startValue.writeExpression(writer, elementType);
final int counterVarIndex, varIndex;
if (boxed) {
// Create two variables, the counter variable and the user-visible loop variable
writer.visitInsn(Opcodes.AUTO_DUP);
counterVarIndex = writer.localCount();
writer.visitVarInsn(elementType.getStoreOpcode(), counterVarIndex);
elementType.writeCast(writer, varType, lineNumber);
var.writeInit(writer, null);
varIndex = var.getLocalIndex();
} else {
// Use the loop variable as the counter variable
var.writeInit(writer, null);
varIndex = counterVarIndex = var.getLocalIndex();
}
endValue.writeExpression(writer, elementType);
final int endVarIndex = writer.localCount();
writer.visitVarInsn(elementType.getStoreOpcode(), endVarIndex);
writer.visitTargetLabel(startLabel);
// Check the condition
switch(kind) {
case INT:
writer.visitVarInsn(Opcodes.ILOAD, counterVarIndex);
writer.visitVarInsn(Opcodes.ILOAD, endVarIndex);
writer.visitJumpInsn(halfOpen ? Opcodes.IF_ICMPGE : Opcodes.IF_ICMPGT, endLabel);
break;
case LONG:
writer.visitVarInsn(Opcodes.LLOAD, counterVarIndex);
writer.visitVarInsn(Opcodes.LLOAD, endVarIndex);
writer.visitJumpInsn(halfOpen ? Opcodes.IF_LCMPGE : Opcodes.IF_LCMPGT, endLabel);
break;
case FLOAT:
writer.visitVarInsn(Opcodes.FLOAD, counterVarIndex);
writer.visitVarInsn(Opcodes.FLOAD, endVarIndex);
writer.visitJumpInsn(halfOpen ? Opcodes.IF_FCMPGE : Opcodes.IF_FCMPGT, endLabel);
break;
case DOUBLE:
writer.visitVarInsn(Opcodes.DLOAD, counterVarIndex);
writer.visitVarInsn(Opcodes.DLOAD, endVarIndex);
writer.visitJumpInsn(halfOpen ? Opcodes.IF_DCMPGE : Opcodes.IF_DCMPGT, endLabel);
break;
case RANGEABLE:
writer.visitVarInsn(Opcodes.ALOAD, counterVarIndex);
writer.visitVarInsn(Opcodes.ALOAD, endVarIndex);
writer.visitLineNumber(lineNumber);
writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "dyvil/collection/range/Rangeable", "compareTo", "(Ldyvil/collection/range/Rangeable;)I", true);
writer.visitJumpInsn(halfOpen ? Opcodes.IFGE : Opcodes.IFGT, endLabel);
break;
}
// Action
if (this.action != null) {
this.action.writeExpression(writer, Types.VOID);
}
// Increment
writer.visitLabel(updateLabel);
switch(kind) {
case INT:
writer.visitIincInsn(counterVarIndex, 1);
if (boxed) {
writer.visitVarInsn(Opcodes.ILOAD, counterVarIndex);
elementType.writeCast(writer, varType, lineNumber);
writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
}
break;
case LONG:
writer.visitVarInsn(Opcodes.LLOAD, counterVarIndex);
writer.visitInsn(Opcodes.LCONST_1);
writer.visitInsn(Opcodes.LADD);
if (boxed) {
writer.visitInsn(Opcodes.DUP2);
elementType.writeCast(writer, varType, lineNumber);
writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
}
writer.visitVarInsn(Opcodes.LSTORE, counterVarIndex);
break;
case FLOAT:
writer.visitVarInsn(Opcodes.FLOAD, counterVarIndex);
writer.visitInsn(Opcodes.FCONST_1);
writer.visitInsn(Opcodes.FADD);
if (boxed) {
writer.visitInsn(Opcodes.DUP);
elementType.writeCast(writer, varType, lineNumber);
writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
}
writer.visitVarInsn(Opcodes.FSTORE, counterVarIndex);
break;
case DOUBLE:
writer.visitVarInsn(Opcodes.DLOAD, counterVarIndex);
writer.visitInsn(Opcodes.DCONST_1);
writer.visitInsn(Opcodes.DADD);
if (boxed) {
writer.visitInsn(Opcodes.DUP2);
elementType.writeCast(writer, varType, lineNumber);
writer.visitVarInsn(varType.getStoreOpcode(), varIndex);
}
writer.visitVarInsn(Opcodes.DSTORE, counterVarIndex);
break;
case RANGEABLE:
writer.visitVarInsn(Opcodes.ALOAD, counterVarIndex);
writer.visitLineNumber(lineNumber);
writer.visitMethodInsn(Opcodes.INVOKEINTERFACE, "dyvil/collection/range/Rangeable", "next", "()Ldyvil/collection/range/Rangeable;", true);
if (elementType.getTheClass() != LazyFields.RANGEABLE_CLASS) {
LazyFields.RANGEABLE.writeCast(writer, elementType, lineNumber);
}
assert !boxed;
writer.visitVarInsn(Opcodes.ASTORE, counterVarIndex);
break;
}
writer.visitJumpInsn(Opcodes.GOTO, startLabel);
// Local Variables
writer.resetLocals(counterVarIndex);
writer.visitLabel(endLabel);
var.writeLocal(writer, scopeLabel, endLabel);
}
use of dyvilx.tools.compiler.ast.type.IType in project Dyvil by Dyvil.
the class ClassGenericType method inferTypes.
@Override
public void inferTypes(IType concrete, ITypeContext typeContext) {
final TypeParameterList classTypeParams = this.getTheClass().getTypeParameters();
for (int i = 0, size = this.arguments.size(); i < size; i++) {
final ITypeParameter typeVar = classTypeParams.get(i);
final IType concreteType = concrete.resolveType(typeVar);
if (concreteType != null) {
this.arguments.get(i).inferTypes(concreteType, typeContext);
}
}
}
Aggregations