// Compiler implementation of the D programming language // Copyright (c) 1999-2012 by Digital Mars // All Rights Reserved // written by Walter Bright // http://www.digitalmars.com // License for redistribution is by either the Artistic License // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. #ifndef DMD_TEMPLATE_H #define DMD_TEMPLATE_H #ifdef __DMC__ #pragma once #endif /* __DMC__ */ #if IN_LLVM #include #endif #include "root.h" #include "arraytypes.h" #include "dsymbol.h" struct OutBuffer; struct Identifier; struct TemplateInstance; struct TemplateParameter; struct TemplateTypeParameter; struct TemplateThisParameter; struct TemplateValueParameter; struct TemplateAliasParameter; struct TemplateTupleParameter; struct Type; struct TypeQualified; struct TypeTypeof; struct Scope; struct Expression; struct AliasDeclaration; struct FuncDeclaration; struct HdrGenState; struct Parameter; enum MATCH; enum PASS; struct Tuple : Object { Objects objects; int dyncast() { return DYNCAST_TUPLE; } // kludge for template.isType() }; struct TemplateDeclaration : ScopeDsymbol { TemplateParameters *parameters; // array of TemplateParameter's TemplateParameters *origParameters; // originals for Ddoc Expression *constraint; TemplateInstances instances; // array of TemplateInstance's TemplateDeclaration *overnext; // next overloaded TemplateDeclaration TemplateDeclaration *overroot; // first in overnext list enum PASS semanticRun; // 1 semantic() run Dsymbol *onemember; // if !=NULL then one member of this template int literal; // this template declaration is a literal int ismixin; // template declaration is only to be used as a mixin enum PROT protection; struct Previous { Previous *prev; Scope *sc; Objects *dedargs; }; Previous *previous; // threaded list of previous instantiation attempts on stack TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, Expression *constraint, Dsymbols *decldefs, int ismixin); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc); int overloadInsert(Dsymbol *s); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); bool hasStaticCtorOrDtor(); const char *kind(); char *toChars(); void emitComment(Scope *sc); void toJson(JsonOut *json); virtual void jsonProperties(JsonOut *json); enum PROT prot(); // void toDocBuffer(OutBuffer *buf); MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag); MATCH leastAsSpecialized(TemplateDeclaration *td2, Expressions *fargs); MATCH deduceFunctionTemplateMatch(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, Objects *dedargs); FuncDeclaration *deduceFunctionTemplate(Loc loc, Scope *sc, Objects *tiargs, Type *tthis, Expressions *fargs, int flags = 0); Object *declareParameter(Scope *sc, TemplateParameter *tp, Object *o); FuncDeclaration *doHeaderInstantiation(Scope *sc, Objects *tdargs, Type *tthis, Expressions *fargs); TemplateDeclaration *isTemplateDeclaration() { return this; } TemplateTupleParameter *isVariadic(); int isOverloadable(); void makeParamNamesVisibleInConstraint(Scope *paramscope, Expressions *fargs); #if IN_LLVM // LDC std::string intrinsicName; #endif }; struct TemplateParameter { /* For type-parameter: * template Foo(ident) // specType is set to NULL * template Foo(ident : specType) * For value-parameter: * template Foo(valType ident) // specValue is set to NULL * template Foo(valType ident : specValue) * For alias-parameter: * template Foo(alias ident) * For this-parameter: * template Foo(this ident) */ Loc loc; Identifier *ident; Declaration *sparam; TemplateParameter(Loc loc, Identifier *ident); virtual TemplateTypeParameter *isTemplateTypeParameter(); virtual TemplateValueParameter *isTemplateValueParameter(); virtual TemplateAliasParameter *isTemplateAliasParameter(); #if DMDV2 virtual TemplateThisParameter *isTemplateThisParameter(); #endif virtual TemplateTupleParameter *isTemplateTupleParameter(); virtual TemplateParameter *syntaxCopy() = 0; virtual void declareParameter(Scope *sc) = 0; virtual void semantic(Scope *) = 0; virtual void print(Object *oarg, Object *oded) = 0; virtual void toCBuffer(OutBuffer *buf, HdrGenState *hgs) = 0; virtual Object *specialization() = 0; virtual Object *defaultArg(Loc loc, Scope *sc) = 0; /* If TemplateParameter's match as far as overloading goes. */ virtual int overloadMatch(TemplateParameter *) = 0; /* Match actual argument against parameter. */ virtual MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0; /* Create dummy argument based on parameter. */ virtual void *dummyArg() = 0; }; struct TemplateTypeParameter : TemplateParameter { /* Syntax: * ident : specType = defaultType */ Type *specType; // type parameter: if !=NULL, this is the type specialization Type *defaultType; static Type *tdummy; TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); TemplateTypeParameter *isTemplateTypeParameter(); TemplateParameter *syntaxCopy(); void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); void *dummyArg(); }; #if DMDV2 struct TemplateThisParameter : TemplateTypeParameter { /* Syntax: * this ident : specType = defaultType */ TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); TemplateThisParameter *isTemplateThisParameter(); TemplateParameter *syntaxCopy(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); }; #endif struct TemplateValueParameter : TemplateParameter { /* Syntax: * valType ident : specValue = defaultValue */ Type *valType; Expression *specValue; Expression *defaultValue; static AA *edummies; TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue); TemplateValueParameter *isTemplateValueParameter(); TemplateParameter *syntaxCopy(); void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); void *dummyArg(); }; struct TemplateAliasParameter : TemplateParameter { /* Syntax: * specType ident : specAlias = defaultAlias */ Type *specType; Object *specAlias; Object *defaultAlias; static Dsymbol *sdummy; TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, Object *specAlias, Object *defaultAlias); TemplateAliasParameter *isTemplateAliasParameter(); TemplateParameter *syntaxCopy(); void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); void *dummyArg(); }; struct TemplateTupleParameter : TemplateParameter { /* Syntax: * ident ... */ TemplateTupleParameter(Loc loc, Identifier *ident); TemplateTupleParameter *isTemplateTupleParameter(); TemplateParameter *syntaxCopy(); void declareParameter(Scope *sc); void semantic(Scope *); void print(Object *oarg, Object *oded); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Object *specialization(); Object *defaultArg(Loc loc, Scope *sc); int overloadMatch(TemplateParameter *); MATCH matchArg(Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); void *dummyArg(); }; struct TemplateInstance : ScopeDsymbol { /* Given: * foo!(args) => * name = foo * tiargs = args */ Identifier *name; //Identifiers idents; Objects *tiargs; // Array of Types/Expressions of template // instance arguments [int*, char, 10*10] Objects tdtypes; // Array of Types/Expressions corresponding // to TemplateDeclaration.parameters // [int, char, 100] TemplateDeclaration *tempdecl; // referenced by foo.bar.abc TemplateInstance *inst; // refer to existing instance TemplateInstance *tinst; // enclosing template instance ScopeDsymbol *argsym; // argument symbol table AliasDeclaration *aliasdecl; // !=NULL if instance is an alias for its // sole member WithScopeSymbol *withsym; // if a member of a with statement enum PASS semanticRun; // has semantic() been done? int semantictiargsdone; // has semanticTiargs() been done? int nest; // for recursion detection int havetempdecl; // 1 if used second constructor Dsymbol *enclosing; // if referencing local symbols, this is the context int speculative; // 1 if only instantiated with errors gagged #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol will be emitted in the output or not before the symbol is used. This can be different from getModule(). */ Module * objFileModule; #endif TemplateInstance(Loc loc, Identifier *temp_id); TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs); static Objects *arraySyntaxCopy(Objects *objs); Dsymbol *syntaxCopy(Dsymbol *); void semantic(Scope *sc, Expressions *fargs); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); void inlineScan(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); Dsymbol *toAlias(); // resolve real symbol const char *kind(); int oneMember(Dsymbol **ps, Identifier *ident); int needsTypeInference(Scope *sc); char *toChars(); const char *mangle(bool isv = false); void printInstantiationTrace(); #if IN_DMD void toObjFile(int multiobj); // compile to .obj file #endif // Internal static void semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); bool semanticTiargs(Scope *sc); bool findTemplateDeclaration(Scope *sc); bool findBestMatch(Scope *sc, Expressions *fargs); void declareParameters(Scope *sc); int hasNestedArgs(Objects *tiargs); Identifier *genIdent(Objects *args); void expandMembers(Scope *sc); void tryExpandMembers(Scope *sc); void trySemantic3(Scope *sc2); TemplateInstance *isTemplateInstance() { return this; } AliasDeclaration *isAliasDeclaration(); #if IN_LLVM bool ignore; // true if the instance must be ignored when codegen'ing Module* emittedInModule; // which module this template instance has been emitted in void codegen(IRState*); #endif }; struct TemplateMixin : TemplateInstance { TypeQualified *tqual; TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs); Dsymbol *syntaxCopy(Dsymbol *s); void semantic(Scope *sc); void semantic2(Scope *sc); void semantic3(Scope *sc); void inlineScan(); const char *kind(); int oneMember(Dsymbol **ps, Identifier *ident); int apply(Dsymbol_apply_ft_t fp, void *param); int hasPointers(); void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toJson(JsonOut *json); #if IN_DMD void toObjFile(int multiobj); // compile to .obj file #endif TemplateMixin *isTemplateMixin() { return this; } #if IN_LLVM void codegen(IRState*); #endif }; Expression *isExpression(Object *o); Dsymbol *isDsymbol(Object *o); Type *isType(Object *o); Tuple *isTuple(Object *o); Parameter *isParameter(Object *o); int arrayObjectIsError(Objects *args); int isError(Object *o); Type *getType(Object *o); Dsymbol *getDsymbol(Object *o); void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg); Object *objectSyntaxCopy(Object *o); #endif /* DMD_TEMPLATE_H */