Add GenericSubscriptExpr to represent subscripting into a generic type.

Swift SVN r2336
This commit is contained in:
Eli Friedman
2012-07-10 23:39:46 +00:00
parent 908cf4573f
commit 43e7559310
8 changed files with 164 additions and 1 deletions

View File

@@ -816,7 +816,7 @@ public:
SourceLoc RBracketLoc, SubscriptDecl *D); SourceLoc RBracketLoc, SubscriptDecl *D);
/// getBase - Retrieve the base of the subscript expression, i.e., the /// getBase - Retrieve the base of the subscript expression, i.e., the
/// value being indexed. This value has existential type. /// value being indexed. This value has archetype type.
Expr *getBase() const { return Base; } Expr *getBase() const { return Base; }
void setBase(Expr *E) { Base = E; } void setBase(Expr *E) { Base = E; }
@@ -843,7 +843,49 @@ public:
return E->getKind() == ExprKind::ArchetypeSubscript; return E->getKind() == ExprKind::ArchetypeSubscript;
} }
}; };
/// GenericSubscriptExpr - Subscripting expressions like a[i] that refer to
/// an element within a container, where the container is a generic type.
class GenericSubscriptExpr : public Expr {
SubscriptDecl *D;
SourceRange Brackets;
Expr *Base;
Expr *Index;
public:
GenericSubscriptExpr(Expr *Base, SourceLoc LBracketLoc, Expr *Index,
SourceLoc RBracketLoc, SubscriptDecl *D);
/// getBase - Retrieve the base of the subscript expression, i.e., the
/// value being indexed. This value has generic type.
Expr *getBase() const { return Base; }
void setBase(Expr *E) { Base = E; }
/// getIndex - Retrieve the index of the subscript expression, i.e., the
/// "offset" into the base value.
Expr *getIndex() const { return Index; }
void setIndex(Expr *E) { Index = E; }
/// getDecl - Retrieve the subscript declaration that this subscripting
/// operation refers to.
SubscriptDecl *getDecl() const { return D; }
void setDecl(SubscriptDecl *D) { this->D = D; }
SourceLoc getLBracketLoc() const { return Brackets.Start; }
SourceLoc getRBracketLoc() const { return Brackets.End; }
SourceRange getSourceRange() const {
return SourceRange(Base->getStartLoc(), Brackets.End);
}
// Implement isa/cast/dyncast/etc.
static bool classof(const GenericSubscriptExpr *) { return true; }
static bool classof(const Expr *E) {
return E->getKind() == ExprKind::GenericSubscript;
}
};
/// OverloadedSubscriptExpr - Subscripting expressions like a[i] that refer to /// OverloadedSubscriptExpr - Subscripting expressions like a[i] that refer to
/// an element within a container, for which overload resolution has found /// an element within a container, for which overload resolution has found
/// multiple potential subscript declarations that may apply. /// multiple potential subscript declarations that may apply.

View File

@@ -74,6 +74,7 @@ EXPR(Subscript, Expr)
UNCHECKED_EXPR(OverloadedSubscript, Expr) UNCHECKED_EXPR(OverloadedSubscript, Expr)
EXPR(ExistentialSubscript, Expr) EXPR(ExistentialSubscript, Expr)
EXPR(ArchetypeSubscript, Expr) EXPR(ArchetypeSubscript, Expr)
EXPR(GenericSubscript, Expr)
EXPR(TupleElement, Expr) EXPR(TupleElement, Expr)
ABSTRACT_EXPR(Capturing, Expr) ABSTRACT_EXPR(Capturing, Expr)
EXPR(Func, CapturingExpr) EXPR(Func, CapturingExpr)

View File

@@ -169,6 +169,19 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*> {
return E; return E;
} }
Expr *visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
if (Expr *Base = doIt(E->getBase()))
E->setBase(Base);
else
return nullptr;
if (Expr *Index = doIt(E->getIndex()))
E->setIndex(Index);
else
return nullptr;
return E;
}
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { return E; } Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { return E; }
Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *E) { Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *E) {
if (!E->getBase()) if (!E->getBase())

View File

@@ -254,6 +254,15 @@ ArchetypeSubscriptExpr(Expr *Base, SourceLoc LBracketLoc, Expr *Index,
"use SubscriptExpr for non-archetype type subscript"); "use SubscriptExpr for non-archetype type subscript");
} }
GenericSubscriptExpr::
GenericSubscriptExpr(Expr *Base, SourceLoc LBracketLoc, Expr *Index,
SourceLoc RBracketLoc, SubscriptDecl *D)
: Expr(ExprKind::GenericSubscript, D? D->getElementType() : Type()),
D(D), Brackets(LBracketLoc, RBracketLoc), Base(Base), Index(Index) {
assert(Base->getType()->getRValueType()->is<BoundGenericType>() &&
"use SubscriptExpr for non-generic type subscript");
}
Expr *OverloadedSubscriptExpr::createWithCopy(Expr *Base, Expr *OverloadedSubscriptExpr::createWithCopy(Expr *Base,
ArrayRef<ValueDecl*> Decls, ArrayRef<ValueDecl*> Decls,
SourceLoc LBracketLoc, SourceLoc LBracketLoc,
@@ -274,6 +283,11 @@ Expr *OverloadedSubscriptExpr::createWithCopy(Expr *Base,
RBracketLoc, RBracketLoc,
cast<SubscriptDecl>(Decls[0])); cast<SubscriptDecl>(Decls[0]));
if (ContainerTy->is<BoundGenericType>())
return new (C) GenericSubscriptExpr(Base, LBracketLoc, Index,
RBracketLoc,
cast<SubscriptDecl>(Decls[0]));
return new (C) SubscriptExpr(Base, LBracketLoc, Index, RBracketLoc, return new (C) SubscriptExpr(Base, LBracketLoc, Index, RBracketLoc,
cast<SubscriptDecl>(Decls[0])); cast<SubscriptDecl>(Decls[0]));
} }
@@ -505,6 +519,14 @@ public:
printRec(E->getIndex()); printRec(E->getIndex());
OS << ')'; OS << ')';
} }
void visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
printCommon(E, "generic_subscript_expr");
OS << '\n';
printRec(E->getBase());
OS << '\n';
printRec(E->getIndex());
OS << ')';
}
void visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { void visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
printCommon(E, "overloaded_subscript_expr"); printCommon(E, "overloaded_subscript_expr");
OS << '\n'; OS << '\n';

View File

@@ -228,10 +228,17 @@ namespace {
void visitExistentialSubscriptExpr(ExistentialSubscriptExpr *E) { void visitExistentialSubscriptExpr(ExistentialSubscriptExpr *E) {
IGF.unimplemented(E->getLBracketLoc(), "existential subscripts"); IGF.unimplemented(E->getLBracketLoc(), "existential subscripts");
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
} }
void visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) { void visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
IGF.unimplemented(E->getLBracketLoc(), "archetype subscripts"); IGF.unimplemented(E->getLBracketLoc(), "archetype subscripts");
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
}
void visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
IGF.unimplemented(E->getLBracketLoc(), "generic subscripts");
IGF.emitFakeExplosion(IGF.getFragileTypeInfo(E->getType()), Out);
} }
void visitTupleShuffleExpr(TupleShuffleExpr *E) { void visitTupleShuffleExpr(TupleShuffleExpr *E) {
@@ -478,6 +485,11 @@ namespace {
return LValue(); return LValue();
} }
LValue visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
IGF.unimplemented(E->getLBracketLoc(), "generic subscripts");
return LValue();
}
LValue visitArchetypeMemberRefExpr(ArchetypeMemberRefExpr *E) { LValue visitArchetypeMemberRefExpr(ArchetypeMemberRefExpr *E) {
IGF.unimplemented(E->getLoc(), "archetype member reference"); IGF.unimplemented(E->getLoc(), "archetype member reference");
return LValue(); return LValue();
@@ -614,6 +626,7 @@ namespace {
NON_LOCATEABLE(SubscriptExpr); NON_LOCATEABLE(SubscriptExpr);
NON_LOCATEABLE(ExistentialSubscriptExpr) NON_LOCATEABLE(ExistentialSubscriptExpr)
NON_LOCATEABLE(ArchetypeSubscriptExpr) NON_LOCATEABLE(ArchetypeSubscriptExpr)
NON_LOCATEABLE(GenericSubscriptExpr)
#undef NON_LOCATEABLE #undef NON_LOCATEABLE
}; };
} }

View File

@@ -275,6 +275,9 @@ public:
CoercedResult visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) { CoercedResult visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
return unchanged(E); return unchanged(E);
} }
CoercedResult visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
return unchanged(E);
}
CoercedResult visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { CoercedResult visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
Type BaseTy = E->getBase()->getType()->getRValueType(); Type BaseTy = E->getBase()->getType()->getRValueType();

View File

@@ -183,6 +183,17 @@ Expr *TypeChecker::semaSubscriptExpr(SubscriptExpr *SE) {
Sub)); Sub));
} }
if (BaseTy->is<BoundGenericType>()) {
// We picked a subscript operator in a generic type; create the
// appropriate AST node.
return semaSubscriptExpr(
new (Context) GenericSubscriptExpr(SE->getBase(),
SE->getLBracketLoc(),
SE->getIndex(),
SE->getRBracketLoc(),
Sub));
}
// Simple case: perform semantic analysis now that we have the declaration. // Simple case: perform semantic analysis now that we have the declaration.
SE->setDecl(Sub); SE->setDecl(Sub);
return semaSubscriptExpr(SE); return semaSubscriptExpr(SE);
@@ -376,6 +387,60 @@ Expr *TypeChecker::semaSubscriptExpr(ArchetypeSubscriptExpr *E) {
} }
Expr *TypeChecker::semaSubscriptExpr(GenericSubscriptExpr *E) {
// Propagate errors up.
if (E->getDecl()->getType()->is<ErrorType>()) {
E->setType(ErrorType::get(Context));
return nullptr;
}
// Ensure that the base is an lvalue, materializing it if is not an
// lvalue yet.
Type ContainerTy = E->getBase()->getType()->getRValueType();
if (Expr *Base = coerceObjectArgument(E->getBase(), ContainerTy))
E->setBase(Base);
else {
E->setType(ErrorType::get(Context));
return nullptr;
}
SubscriptDecl *SubDecl = E->getDecl();
// Determine the index type.
Type IndexType = SubDecl->getIndices()->getType();
IndexType = substMemberTypeWithBase(IndexType, ContainerTy);
if (!IndexType)
return nullptr;
// Coerce the index argument to the index type.
Expr *Index = coerceToType(E->getIndex(), IndexType);
if (!Index) {
diagnose(E->getBase()->getLoc(), diag::while_converting_subscript_index,
IndexType)
<< E->getIndex()->getSourceRange();
E->setType(ErrorType::get(Context));
return nullptr;
}
E->setIndex(Index);
// Determine the value type.
Type ValueType = SubDecl->getElementType();
ValueType = substMemberTypeWithBase(ValueType, ContainerTy);
if (!ValueType) {
E->setType(ErrorType::get(Context));
return nullptr;
}
ValueType = LValueType::get(ValueType,
LValueType::Qual::DefaultForMemberAccess,
Context);
E->setType(ValueType);
return E;
}
/// \brief Determine whether this expression refers to a type directly (ignoring /// \brief Determine whether this expression refers to a type directly (ignoring
/// parentheses), rather than some variable of metatype type. /// parentheses), rather than some variable of metatype type.
static bool isDirectTypeReference(Expr *E) { static bool isDirectTypeReference(Expr *E) {
@@ -890,6 +955,9 @@ public:
Expr *visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) { Expr *visitArchetypeSubscriptExpr(ArchetypeSubscriptExpr *E) {
return TC.semaSubscriptExpr(E); return TC.semaSubscriptExpr(E);
} }
Expr *visitGenericSubscriptExpr(GenericSubscriptExpr *E) {
return TC.semaSubscriptExpr(E);
}
Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) { Expr *visitOverloadedSubscriptExpr(OverloadedSubscriptExpr *E) {
E->setType(UnstructuredUnresolvedType::get(TC.Context)); E->setType(UnstructuredUnresolvedType::get(TC.Context));

View File

@@ -316,6 +316,7 @@ public:
Expr *semaSubscriptExpr(SubscriptExpr *SE); Expr *semaSubscriptExpr(SubscriptExpr *SE);
Expr *semaSubscriptExpr(ExistentialSubscriptExpr *SE); Expr *semaSubscriptExpr(ExistentialSubscriptExpr *SE);
Expr *semaSubscriptExpr(ArchetypeSubscriptExpr *SE); Expr *semaSubscriptExpr(ArchetypeSubscriptExpr *SE);
Expr *semaSubscriptExpr(GenericSubscriptExpr *SE);
Expr *semaApplyExpr(ApplyExpr *E); Expr *semaApplyExpr(ApplyExpr *E);
Expr *semaUnresolvedDotExpr(UnresolvedDotExpr *E); Expr *semaUnresolvedDotExpr(UnresolvedDotExpr *E);
void typeCheckIgnoredExpr(Expr *E); void typeCheckIgnoredExpr(Expr *E);