Initial work on the `new' GenTemplateInstance.

This commit is contained in:
Roberto Raggi
2009-10-26 17:54:32 +01:00
parent b4744214c6
commit 82ecb2c7b3
6 changed files with 359 additions and 165 deletions

View File

@@ -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); }

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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;

View File

@@ -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));