forked from qt-creator/qt-creator
Initial work on the `new' GenTemplateInstance.
This commit is contained in:
@@ -1,145 +1,354 @@
|
||||
|
||||
#include "GenTemplateInstance.h"
|
||||
#include "Overview.h"
|
||||
|
||||
#include <Control.h>
|
||||
#include <Scope.h>
|
||||
#include <Names.h>
|
||||
#include <Symbols.h>
|
||||
#include <CoreTypes.h>
|
||||
#include <Literals.h>
|
||||
|
||||
#include <QtCore/QVarLengthArray>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
using namespace CPlusPlus;
|
||||
|
||||
GenTemplateInstance::GenTemplateInstance(Control *control, const Substitution &substitution)
|
||||
: _control(control),
|
||||
namespace {
|
||||
|
||||
class ApplySubstitution
|
||||
{
|
||||
public:
|
||||
ApplySubstitution(const LookupContext &context, const GenTemplateInstance::Substitution &substitution);
|
||||
~ApplySubstitution();
|
||||
|
||||
Control *control() const { return context.control(); }
|
||||
|
||||
FullySpecifiedType operator()(Name *name);
|
||||
FullySpecifiedType operator()(const FullySpecifiedType &type);
|
||||
|
||||
int findSubstitution(Identifier *id) const;
|
||||
FullySpecifiedType applySubstitution(int index) const;
|
||||
|
||||
private:
|
||||
class ApplyToType: protected TypeVisitor
|
||||
{
|
||||
public:
|
||||
ApplyToType(ApplySubstitution *q)
|
||||
: q(q) {}
|
||||
|
||||
FullySpecifiedType operator()(const FullySpecifiedType &ty)
|
||||
{
|
||||
FullySpecifiedType previousType = switchType(ty);
|
||||
accept(ty.type());
|
||||
return switchType(previousType);
|
||||
}
|
||||
|
||||
protected:
|
||||
using TypeVisitor::visit;
|
||||
|
||||
Control *control() const
|
||||
{ return q->control(); }
|
||||
|
||||
FullySpecifiedType switchType(const FullySpecifiedType &type)
|
||||
{
|
||||
FullySpecifiedType previousType = _type;
|
||||
_type = type;
|
||||
return previousType;
|
||||
}
|
||||
|
||||
virtual void visit(VoidType *)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
virtual void visit(IntegerType *)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
virtual void visit(FloatType *)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
virtual void visit(PointerToMemberType *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO; // ### TODO
|
||||
}
|
||||
|
||||
virtual void visit(PointerType *ptrTy)
|
||||
{
|
||||
_type.setType(control()->pointerType(operator()(ptrTy->elementType())));
|
||||
}
|
||||
|
||||
virtual void visit(ReferenceType *refTy)
|
||||
{
|
||||
_type.setType(control()->referenceType(operator()(refTy->elementType())));
|
||||
}
|
||||
|
||||
virtual void visit(ArrayType *arrayTy)
|
||||
{
|
||||
_type.setType(control()->arrayType(operator()(arrayTy->elementType()), arrayTy->size()));
|
||||
}
|
||||
|
||||
virtual void visit(NamedType *ty)
|
||||
{
|
||||
FullySpecifiedType n = q->operator ()(ty->name());
|
||||
_type.setType(n.type());
|
||||
}
|
||||
|
||||
virtual void visit(Function *funTy)
|
||||
{
|
||||
Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name());
|
||||
fun->setScope(funTy->scope());
|
||||
fun->setConst(funTy->isConst());
|
||||
fun->setVolatile(funTy->isVolatile());
|
||||
fun->setVirtual(funTy->isVirtual());
|
||||
fun->setAmbiguous(funTy->isAmbiguous());
|
||||
fun->setVariadic(funTy->isVariadic());
|
||||
|
||||
fun->setReturnType(q->operator ()(funTy->returnType()));
|
||||
|
||||
for (unsigned i = 0; i < funTy->argumentCount(); ++i) {
|
||||
Argument *originalArgument = funTy->argumentAt(i)->asArgument();
|
||||
Argument *arg = control()->newArgument(/*sourceLocation*/ 0,
|
||||
originalArgument->name());
|
||||
|
||||
arg->setType(q->operator ()(originalArgument->type()));
|
||||
arg->setInitializer(originalArgument->hasInitializer());
|
||||
fun->arguments()->enterSymbol(arg);
|
||||
}
|
||||
|
||||
_type.setType(fun);
|
||||
}
|
||||
|
||||
virtual void visit(Namespace *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(Class *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(Enum *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ForwardClassDeclaration *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCClass *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCProtocol *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCMethod *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCForwardClassDeclaration *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void visit(ObjCForwardProtocolDeclaration *)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
private:
|
||||
ApplySubstitution *q;
|
||||
FullySpecifiedType _type;
|
||||
};
|
||||
|
||||
class ApplyToName: protected NameVisitor
|
||||
{
|
||||
public:
|
||||
ApplyToName(ApplySubstitution *q): q(q) {}
|
||||
|
||||
FullySpecifiedType operator()(Name *name)
|
||||
{
|
||||
FullySpecifiedType previousType = switchType(FullySpecifiedType());
|
||||
accept(name);
|
||||
return switchType(previousType);
|
||||
}
|
||||
|
||||
protected:
|
||||
Control *control() const
|
||||
{ return q->control(); }
|
||||
|
||||
int findSubstitution(Identifier *id) const
|
||||
{ return q->findSubstitution(id); }
|
||||
|
||||
FullySpecifiedType applySubstitution(int index) const
|
||||
{ return q->applySubstitution(index); }
|
||||
|
||||
FullySpecifiedType switchType(const FullySpecifiedType &type)
|
||||
{
|
||||
FullySpecifiedType previousType = _type;
|
||||
_type = type;
|
||||
return previousType;
|
||||
}
|
||||
|
||||
virtual void visit(NameId *name)
|
||||
{
|
||||
int index = findSubstitution(name->identifier());
|
||||
|
||||
if (index != -1)
|
||||
_type = applySubstitution(index);
|
||||
|
||||
else
|
||||
_type = control()->namedType(name);
|
||||
}
|
||||
|
||||
virtual void visit(TemplateNameId *name)
|
||||
{
|
||||
QVarLengthArray<FullySpecifiedType, 8> arguments(name->templateArgumentCount());
|
||||
for (unsigned i = 0; i < name->templateArgumentCount(); ++i) {
|
||||
FullySpecifiedType argTy = name->templateArgumentAt(i);
|
||||
arguments[i] = q->operator ()(argTy);
|
||||
}
|
||||
|
||||
TemplateNameId *templId = control()->templateNameId(name->identifier(), arguments.data(), arguments.size());
|
||||
_type = control()->namedType(templId);
|
||||
}
|
||||
|
||||
virtual void visit(QualifiedNameId *name)
|
||||
{
|
||||
QVarLengthArray<Name *, 8> names(name->nameCount());
|
||||
for (unsigned i = 0; i < name->nameCount(); ++i) {
|
||||
Name *n = name->nameAt(i);
|
||||
|
||||
if (TemplateNameId *templId = n->asTemplateNameId()) {
|
||||
QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
|
||||
for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) {
|
||||
FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
|
||||
arguments[templateArgIndex] = q->operator ()(argTy);
|
||||
}
|
||||
|
||||
n = control()->templateNameId(templId->identifier(), arguments.data(), arguments.size());
|
||||
}
|
||||
|
||||
names[i] = n;
|
||||
}
|
||||
|
||||
QualifiedNameId *q = control()->qualifiedNameId(names.data(), names.size(), name->isGlobal());
|
||||
_type = control()->namedType(q);
|
||||
}
|
||||
|
||||
virtual void visit(DestructorNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo(name);
|
||||
}
|
||||
|
||||
virtual void visit(OperatorNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo(name);
|
||||
}
|
||||
|
||||
virtual void visit(ConversionNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo(name);
|
||||
}
|
||||
|
||||
virtual void visit(SelectorNameId *name)
|
||||
{
|
||||
Overview oo;
|
||||
qWarning() << "ignored name:" << oo(name);
|
||||
}
|
||||
|
||||
private:
|
||||
ApplySubstitution *q;
|
||||
FullySpecifiedType _type;
|
||||
};
|
||||
|
||||
public: // attributes
|
||||
LookupContext context;
|
||||
GenTemplateInstance::Substitution substitution;
|
||||
|
||||
private:
|
||||
ApplyToType applyToType;
|
||||
ApplyToName applyToName;
|
||||
};
|
||||
|
||||
ApplySubstitution::ApplySubstitution(const LookupContext &context, const GenTemplateInstance::Substitution &substitution)
|
||||
: context(context), substitution(substitution), applyToType(this), applyToName(this)
|
||||
{ }
|
||||
|
||||
ApplySubstitution::~ApplySubstitution()
|
||||
{
|
||||
}
|
||||
|
||||
FullySpecifiedType ApplySubstitution::operator()(Name *name)
|
||||
{ return applyToName(name); }
|
||||
|
||||
FullySpecifiedType ApplySubstitution::operator()(const FullySpecifiedType &type)
|
||||
{ return applyToType(type); }
|
||||
|
||||
int ApplySubstitution::findSubstitution(Identifier *id) const
|
||||
{
|
||||
Q_ASSERT(id != 0);
|
||||
|
||||
for (int index = 0; index < substitution.size(); ++index) {
|
||||
QPair<Identifier *, FullySpecifiedType> s = substitution.at(index);
|
||||
|
||||
if (id->isEqualTo(s.first))
|
||||
return index;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
FullySpecifiedType ApplySubstitution::applySubstitution(int index) const
|
||||
{
|
||||
Q_ASSERT(index != -1);
|
||||
Q_ASSERT(index < substitution.size());
|
||||
|
||||
return substitution.at(index).second;
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
GenTemplateInstance::GenTemplateInstance(const LookupContext &context, const Substitution &substitution)
|
||||
: _symbol(0),
|
||||
_context(context),
|
||||
_substitution(substitution)
|
||||
{ }
|
||||
|
||||
FullySpecifiedType GenTemplateInstance::operator()(const FullySpecifiedType &ty)
|
||||
{ return subst(ty); }
|
||||
|
||||
FullySpecifiedType GenTemplateInstance::subst(Name *name)
|
||||
FullySpecifiedType GenTemplateInstance::operator()(Symbol *symbol)
|
||||
{
|
||||
if (TemplateNameId *t = name->asTemplateNameId()) {
|
||||
QVarLengthArray<FullySpecifiedType, 8> args(t->templateArgumentCount());
|
||||
ApplySubstitution o(_context, _substitution);
|
||||
return o(symbol->type());
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < t->templateArgumentCount(); ++i)
|
||||
args[i] = subst(t->templateArgumentAt(i));
|
||||
Control *GenTemplateInstance::control() const
|
||||
{ return _context.control(); }
|
||||
|
||||
TemplateNameId *n = _control->templateNameId(t->identifier(),
|
||||
args.data(), args.size());
|
||||
int GenTemplateInstance::findSubstitution(Identifier *id) const
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
return FullySpecifiedType(_control->namedType(n));
|
||||
} else if (name->isQualifiedNameId()) {
|
||||
// ### implement me
|
||||
for (; index < _substitution.size(); ++index) {
|
||||
const QPair<Identifier *, FullySpecifiedType> s = _substitution.at(index);
|
||||
|
||||
if (id->isEqualTo(s.first))
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < _substitution.size(); ++i) {
|
||||
const QPair<Name *, FullySpecifiedType> s = _substitution.at(i);
|
||||
if (name->isEqualTo(s.first))
|
||||
return s.second;
|
||||
}
|
||||
|
||||
return FullySpecifiedType(_control->namedType(name));
|
||||
return index;
|
||||
}
|
||||
|
||||
FullySpecifiedType GenTemplateInstance::subst(const FullySpecifiedType &ty)
|
||||
{
|
||||
FullySpecifiedType previousType = switchType(ty);
|
||||
TypeVisitor::accept(ty.type());
|
||||
return switchType(previousType);
|
||||
}
|
||||
|
||||
FullySpecifiedType GenTemplateInstance::switchType(const FullySpecifiedType &type)
|
||||
{
|
||||
FullySpecifiedType previousType = _type;
|
||||
_type = type;
|
||||
return previousType;
|
||||
}
|
||||
|
||||
// types
|
||||
void GenTemplateInstance::visit(PointerToMemberType * /*ty*/)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
void GenTemplateInstance::visit(PointerType *ty)
|
||||
{
|
||||
FullySpecifiedType elementType = subst(ty->elementType());
|
||||
_type.setType(_control->pointerType(elementType));
|
||||
}
|
||||
|
||||
void GenTemplateInstance::visit(ReferenceType *ty)
|
||||
{
|
||||
FullySpecifiedType elementType = subst(ty->elementType());
|
||||
_type.setType(_control->referenceType(elementType));
|
||||
}
|
||||
|
||||
void GenTemplateInstance::visit(ArrayType *ty)
|
||||
{
|
||||
FullySpecifiedType elementType = subst(ty->elementType());
|
||||
_type.setType(_control->arrayType(elementType, ty->size()));
|
||||
}
|
||||
|
||||
void GenTemplateInstance::visit(NamedType *ty)
|
||||
{
|
||||
Name *name = ty->name();
|
||||
_type.setType(subst(name).type());
|
||||
}
|
||||
|
||||
void GenTemplateInstance::visit(Function *ty)
|
||||
{
|
||||
Name *name = ty->name();
|
||||
FullySpecifiedType returnType = subst(ty->returnType());
|
||||
|
||||
Function *fun = _control->newFunction(0, name);
|
||||
fun->setScope(ty->scope());
|
||||
fun->setConst(ty->isConst());
|
||||
fun->setVolatile(ty->isVolatile());
|
||||
fun->setReturnType(returnType);
|
||||
for (unsigned i = 0; i < ty->argumentCount(); ++i) {
|
||||
Symbol *arg = ty->argumentAt(i);
|
||||
FullySpecifiedType argTy = subst(arg->type());
|
||||
Argument *newArg = _control->newArgument(0, arg->name());
|
||||
newArg->setType(argTy);
|
||||
fun->arguments()->enterSymbol(newArg);
|
||||
}
|
||||
_type.setType(fun);
|
||||
}
|
||||
|
||||
void GenTemplateInstance::visit(VoidType *)
|
||||
{ /* nothing to do*/ }
|
||||
|
||||
void GenTemplateInstance::visit(IntegerType *)
|
||||
{ /* nothing to do*/ }
|
||||
|
||||
void GenTemplateInstance::visit(FloatType *)
|
||||
{ /* nothing to do*/ }
|
||||
|
||||
void GenTemplateInstance::visit(Namespace *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(Class *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(Enum *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
// names
|
||||
void GenTemplateInstance::visit(NameId *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(TemplateNameId *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(DestructorNameId *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(OperatorNameId *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(ConversionNameId *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
void GenTemplateInstance::visit(QualifiedNameId *)
|
||||
{ Q_ASSERT(false); }
|
||||
|
||||
|
||||
@@ -5,51 +5,29 @@
|
||||
#include <NameVisitor.h>
|
||||
#include <FullySpecifiedType.h>
|
||||
|
||||
#include "LookupContext.h"
|
||||
|
||||
#include <QtCore/QList>
|
||||
#include <QtCore/QPair>
|
||||
|
||||
namespace CPlusPlus {
|
||||
|
||||
class CPLUSPLUS_EXPORT GenTemplateInstance: protected TypeVisitor, protected NameVisitor
|
||||
class CPLUSPLUS_EXPORT GenTemplateInstance
|
||||
{
|
||||
public:
|
||||
typedef QList< QPair<Name *, FullySpecifiedType> > Substitution;
|
||||
typedef QList< QPair<Identifier *, FullySpecifiedType> > Substitution;
|
||||
|
||||
public:
|
||||
GenTemplateInstance(Control *control, const Substitution &substitution);
|
||||
GenTemplateInstance(const LookupContext &context, const Substitution &substitution);
|
||||
|
||||
FullySpecifiedType operator()(const FullySpecifiedType &ty);
|
||||
FullySpecifiedType operator()(Symbol *symbol);
|
||||
|
||||
protected:
|
||||
FullySpecifiedType subst(Name *name);
|
||||
FullySpecifiedType subst(const FullySpecifiedType &ty);
|
||||
|
||||
FullySpecifiedType switchType(const FullySpecifiedType &type);
|
||||
|
||||
virtual void visit(PointerToMemberType * /*ty*/);
|
||||
virtual void visit(PointerType *ty);
|
||||
virtual void visit(ReferenceType *ty);
|
||||
virtual void visit(ArrayType *ty);
|
||||
virtual void visit(NamedType *ty);
|
||||
virtual void visit(Function *ty);
|
||||
virtual void visit(VoidType *);
|
||||
virtual void visit(IntegerType *);
|
||||
virtual void visit(FloatType *);
|
||||
virtual void visit(Namespace *);
|
||||
virtual void visit(Class *);
|
||||
virtual void visit(Enum *);
|
||||
|
||||
// names
|
||||
virtual void visit(NameId *);
|
||||
virtual void visit(TemplateNameId *);
|
||||
virtual void visit(DestructorNameId *);
|
||||
virtual void visit(OperatorNameId *);
|
||||
virtual void visit(ConversionNameId *);
|
||||
virtual void visit(QualifiedNameId *);
|
||||
Control *control() const;
|
||||
int findSubstitution(Identifier *id) const;
|
||||
|
||||
private:
|
||||
Control *_control;
|
||||
FullySpecifiedType _type;
|
||||
Symbol *_symbol;
|
||||
LookupContext _context;
|
||||
const Substitution _substitution;
|
||||
};
|
||||
|
||||
|
||||
@@ -347,8 +347,10 @@ QList<Scope *> LookupContext::buildVisibleScopes()
|
||||
}
|
||||
|
||||
QList<Scope *> LookupContext::visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const
|
||||
{ return visibleScopes(result.second); }
|
||||
|
||||
QList<Scope *> LookupContext::visibleScopes(Symbol *symbol) const
|
||||
{
|
||||
Symbol *symbol = result.second;
|
||||
QList<Scope *> scopes;
|
||||
for (Scope *scope = symbol->scope(); scope; scope = scope->enclosingScope())
|
||||
scopes.append(scope);
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
QList<Scope *> visibleScopes() const
|
||||
{ return _visibleScopes; }
|
||||
|
||||
QList<Scope *> visibleScopes(Symbol *symbol) const;
|
||||
QList<Scope *> visibleScopes(const QPair<FullySpecifiedType, Symbol *> &result) const;
|
||||
|
||||
QList<Scope *> expand(const QList<Scope *> &scopes) const;
|
||||
|
||||
@@ -695,7 +695,7 @@ ResolveExpression::resolveMember(Name *memberName, Class *klass,
|
||||
QList<Scope *> scopes;
|
||||
_context.expand(klass->members(), _context.visibleScopes(), &scopes);
|
||||
|
||||
QList<Symbol *> candidates = _context.resolve(memberName, scopes);
|
||||
const QList<Symbol *> candidates = _context.resolve(memberName, scopes);
|
||||
|
||||
foreach (Symbol *candidate, candidates) {
|
||||
FullySpecifiedType ty = candidate->type();
|
||||
@@ -710,13 +710,17 @@ ResolveExpression::resolveMember(Name *memberName, Class *klass,
|
||||
for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) {
|
||||
FullySpecifiedType templArgTy = templId->templateArgumentAt(i);
|
||||
|
||||
if (i < klass->templateParameterCount())
|
||||
subst.append(qMakePair(klass->templateParameterAt(i)->name(),
|
||||
templArgTy));
|
||||
if (i < klass->templateParameterCount()) {
|
||||
Name *templArgName = klass->templateParameterAt(i)->name();
|
||||
if (templArgName && templArgName->identifier()) {
|
||||
Identifier *templArgId = templArgName->identifier();
|
||||
subst.append(qMakePair(templArgId, templArgTy));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GenTemplateInstance inst(control(), subst);
|
||||
ty = inst(ty);
|
||||
GenTemplateInstance inst(_context, subst);
|
||||
ty = inst(candidate);
|
||||
}
|
||||
|
||||
results.append(Result(ty, candidate));
|
||||
|
||||
Reference in New Issue
Block a user