use of dyvilx.tools.compiler.ast.type.TypeList in project Dyvil by Dyvil.
the class GenericType method getConcreteTypes.
public static TypeList getConcreteTypes(TypeList types, ITypeContext context) {
TypeList newTypes = null;
for (int i = 0, count = types.size(); i < count; i++) {
final IType original = types.get(i);
final IType concrete = original.getConcreteType(context);
if (newTypes != null) {
newTypes.set(i, concrete);
} else if (concrete != original) {
// If there is a single mismatch, create the array and copy previous elements
newTypes = types.copy();
newTypes.set(i, concrete);
}
}
return newTypes != null ? newTypes : types;
}
use of dyvilx.tools.compiler.ast.type.TypeList in project Dyvil by Dyvil.
the class Types method addSuperClasses.
private static void addSuperClasses(IType type, Collection<IClass> types) {
final IClass theClass = type.getTheClass();
if (theClass == null) {
return;
}
types.add(theClass);
final IType superType = theClass.getSuperType();
if (superType != null) {
addSuperClasses(superType, types);
}
final TypeList interfaces = theClass.getInterfaces();
if (interfaces == null) {
return;
}
for (int i = 0, count = interfaces.size(); i < count; i++) {
addSuperClasses(interfaces.get(i), types);
}
}
use of dyvilx.tools.compiler.ast.type.TypeList in project Dyvil by Dyvil.
the class LambdaExpr method makeType.
@NonNull
private LambdaType makeType() {
final int count = this.parameters.size();
final LambdaType lambdaType = new LambdaType();
final TypeList arguments = lambdaType.getArguments();
for (int i = 0; i < count; i++) {
arguments.add(this.parameters.get(i).getType());
}
arguments.add(this.returnType != null ? this.returnType : Types.UNKNOWN);
this.flags |= LAMBDA_TYPE_INFERRED;
return lambdaType;
}
use of dyvilx.tools.compiler.ast.type.TypeList in project Dyvil by Dyvil.
the class TupleExpr method getType.
@Override
public IType getType() {
if (this.tupleType != null) {
return this.tupleType;
}
final int arity = this.values.size();
final TupleType tupleType = new TupleType(arity);
final TypeList arguments = tupleType.getArguments();
for (int i = 0; i < arity; i++) {
arguments.add(this.values.get(i).getType());
}
return this.tupleType = tupleType;
}
use of dyvilx.tools.compiler.ast.type.TypeList in project Dyvil by Dyvil.
the class TypeParser method parse.
@Override
public void parse(IParserManager pm, IToken token) {
final int type = token.type();
switch(this.mode) {
case NAME:
{
if ((this.flags & NAMED_ONLY) == 0) {
switch(type) {
case DyvilSymbols.AT:
Annotation a = new CodeAnnotation(token.raw());
pm.pushParser(new AnnotationParser(a));
this.type = new AnnotatedType(a);
this.mode = ANNOTATION_END;
return;
case BaseSymbols.OPEN_PARENTHESIS:
{
final TypeList arguments;
if (this.parentType != null) {
final LambdaType lambdaType = new LambdaType();
lambdaType.setExtension(true);
this.type = lambdaType;
arguments = lambdaType.getArguments();
arguments.add(this.parentType);
} else {
final TupleType tupleType = new TupleType();
this.type = tupleType;
arguments = tupleType.getArguments();
}
pm.pushParser(new TypeListParser(arguments));
this.mode = TUPLE_END;
return;
}
case BaseSymbols.OPEN_SQUARE_BRACKET:
{
final ArrayType arrayType = new ArrayType();
switch(token.next().type()) {
case DyvilKeywords.FINAL:
arrayType.setMutability(Mutability.IMMUTABLE);
pm.skip();
break;
case DyvilKeywords.VAR:
arrayType.setMutability(Mutability.MUTABLE);
pm.skip();
break;
}
this.mode = ARRAY_COLON;
this.type = arrayType;
pm.pushParser(new TypeParser(arrayType::setElementType));
return;
}
case DyvilSymbols.ARROW_RIGHT:
{
if ((this.flags & IGNORE_LAMBDA) != 0) {
pm.popParser(true);
return;
}
final LambdaType lambdaType = new LambdaType(token.raw());
final TypeList arguments = lambdaType.getArguments();
if (this.parentType != null) {
arguments.add(this.parentType);
}
pm.pushParser(this.subParser(arguments));
this.type = lambdaType;
this.mode = LAMBDA_END;
return;
}
case DyvilKeywords.NULL:
this.type = Types.NULL;
this.mode = END;
return;
case DyvilSymbols.UNDERSCORE:
this.type = new WildcardType(token.raw(), Variance.COVARIANT);
this.mode = END;
return;
case Tokens.SYMBOL_IDENTIFIER:
final Name name = token.nameValue();
final int closeAngleIndex;
if ((this.flags & CLOSE_ANGLE) == 0 || (closeAngleIndex = name.unqualified.indexOf('>')) < 0) {
// SYMBOL_IDENTIFIER type
final PrefixType prefixType = new PrefixType(token.raw(), name);
pm.pushParser(this.subParser(prefixType.getArguments()).withFlags(IGNORE_OPERATOR | IGNORE_LAMBDA));
this.type = prefixType;
this.mode = END;
return;
}
if (closeAngleIndex == 0) {
// Token starts with a >
// Handles Type< > gracefully
pm.popParser(true);
return;
}
// strip the trailing > and reparse the first part of the token
// Handles Type<_> gracefully
pm.splitReparse(token, closeAngleIndex);
return;
}
}
if (!Tokens.isIdentifier(type)) {
if (isTerminator(type)) {
pm.popParser(true);
return;
}
pm.report(Markers.syntaxError(token, "type.invalid", token.toString()));
return;
}
final Name name = token.nameValue();
final IToken next = token.next();
if (isGenericStart(next, next.type())) {
this.type = new NamedGenericType(token.raw(), this.parentType, name);
this.mode = GENERICS;
return;
}
this.type = new NamedType(token.raw(), name, this.parentType);
this.mode = END;
return;
}
case TUPLE_END:
{
if (type != BaseSymbols.CLOSE_PARENTHESIS) {
pm.reparse();
pm.report(token, "type.tuple.close_paren");
}
final IToken nextToken = token.next();
if (nextToken.type() == DyvilSymbols.ARROW_RIGHT) {
final LambdaType lambdaType;
if (this.type instanceof LambdaType) {
lambdaType = (LambdaType) this.type;
} else {
lambdaType = new LambdaType(nextToken.raw(), ((TupleType) this.type).getArguments());
this.type = lambdaType;
}
lambdaType.setPosition(nextToken);
this.mode = LAMBDA_END;
pm.skip();
pm.pushParser(this.subParser(lambdaType.getArguments()));
return;
}
if (this.parentType != null) {
pm.report(nextToken, "type.tuple.lambda_arrow");
}
this.type.expandPosition(token);
this.mode = END;
return;
}
case LAMBDA_END:
this.type.expandPosition(token.prev());
this.consumer.setType(this.type);
pm.popParser(true);
return;
case ARRAY_COLON:
if (type == BaseSymbols.COLON) {
final MapType mapType = new MapType(this.type.getMutability(), ((ArrayType) this.type).getElementType());
this.type = mapType;
this.mode = ARRAY_END;
pm.pushParser(new TypeParser(mapType.getArguments()));
return;
}
// Fallthrough
case ARRAY_END:
this.type.expandPosition(token);
this.mode = END;
if (type != BaseSymbols.CLOSE_SQUARE_BRACKET) {
pm.reparse();
pm.report(token, "type.array.close_bracket");
}
return;
case GENERICS:
if (isGenericStart(token, type)) {
pm.splitJump(token, 1);
pm.pushParser(new TypeListParser(((GenericType) this.type).getArguments(), true));
this.mode = GENERICS_END;
return;
}
return;
case ANNOTATION_END:
this.mode = END;
pm.pushParser(this.subParser((ITyped) this.type), true);
return;
case GENERICS_END:
this.mode = END;
if (isGenericEnd(token, type)) {
pm.splitJump(token, 1);
return;
}
pm.report(token, "type.generic.close_angle");
// Fallthrough
case END:
{
switch(type) {
case BaseSymbols.DOT:
pm.pushParser(new TypeParser(this, this.type, this.flags));
return;
case BaseSymbols.OPEN_SQUARE_BRACKET:
{
final IToken next = token.next();
if (next.type() == BaseSymbols.CLOSE_SQUARE_BRACKET) {
this.type = new ArrayType(this.type);
pm.report(Markers.syntaxWarning(token.to(next), "type.array.java"));
pm.skip();
return;
}
break;
}
case Tokens.SYMBOL_IDENTIFIER:
{
if ((this.flags & NAMED_ONLY) != 0) {
break;
}
if ((this.flags & CLOSE_ANGLE) != 0) {
final String string = token.stringValue();
int index = string.indexOf('>');
if (index == 0) {
// ... >
pm.splitJump(token, 1);
break;
} else if (index > 0) {
// ... SYMBOL>
pm.splitJump(token, index);
this.type = new PostfixType(token.raw(), Name.fromUnqualified(string.substring(0, index)), this.type);
return;
}
}
final IToken next = token.next();
final boolean leftNeighbor = token.prev().isNeighboring(token);
final boolean rightNeighbor = token.isNeighboring(next);
if (isTerminator(next.type()) || leftNeighbor && !rightNeighbor) {
// type_OPERATOR
this.type = new PostfixType(token.raw(), token.nameValue(), this.type);
// move stays END
return;
}
if (leftNeighbor != rightNeighbor || (this.flags & IGNORE_OPERATOR) != 0) {
// type end
break;
}
// Parse part of an infix operator
// type SYMBOL type
// type_SYMBOL_type
final InfixTypeChain chain;
if (this.type.typeTag() == IType.INFIX_CHAIN) {
chain = (InfixTypeChain) this.type;
} else {
chain = new InfixTypeChain();
chain.addOperand(this.type);
this.type = chain;
}
chain.addOperator(token.nameValue(), token.raw());
pm.pushParser(this.subParser(chain::addOperand).withFlags(IGNORE_OPERATOR));
return;
}
case DyvilSymbols.ARROW_RIGHT:
// all these flags have to be unset
if (this.parentType == null && (this.flags & (NAMED_ONLY | IGNORE_OPERATOR | IGNORE_LAMBDA)) == 0) {
final LambdaType lambdaType = new LambdaType(token.raw(), this.type);
this.type = lambdaType;
this.mode = LAMBDA_END;
pm.pushParser(this.subParser(lambdaType.getArguments()));
return;
}
break;
}
if (this.type != null) {
this.consumer.setType(this.type);
}
pm.popParser(true);
}
}
}
Aggregations