1 2 /* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2021 by The D Language Foundation, All Rights Reserved 4 * written by Walter Bright 5 * http://www.digitalmars.com 6 * Distributed under the Boost Software License, Version 1.0. 7 * http://www.boost.org/LICENSE_1_0.txt 8 * https://github.com/dlang/dmd/blob/master/src/dmd/template.h 9 */ 10 11 #pragma once 12 13 #include "arraytypes.h" 14 #include "dsymbol.h" 15 16 class Identifier; 17 class TemplateInstance; 18 class TemplateParameter; 19 class TemplateTypeParameter; 20 class TemplateThisParameter; 21 class TemplateValueParameter; 22 class TemplateAliasParameter; 23 class TemplateTupleParameter; 24 class Type; 25 class TypeQualified; 26 struct Scope; 27 class Expression; 28 class FuncDeclaration; 29 class Parameter; 30 31 class Tuple : public RootObject 32 { 33 public: 34 Objects objects; 35 36 // kludge for template.isType() dyncast()37 DYNCAST dyncast() const { return DYNCAST_TUPLE; } 38 toChars()39 const char *toChars() const { return objects.toChars(); } 40 }; 41 42 struct TemplatePrevious 43 { 44 TemplatePrevious *prev; 45 Scope *sc; 46 Objects *dedargs; 47 }; 48 49 class TemplateDeclaration : public ScopeDsymbol 50 { 51 public: 52 TemplateParameters *parameters; // array of TemplateParameter's 53 54 TemplateParameters *origParameters; // originals for Ddoc 55 Expression *constraint; 56 57 // Hash table to look up TemplateInstance's of this TemplateDeclaration 58 void *instances; 59 60 TemplateDeclaration *overnext; // next overloaded TemplateDeclaration 61 TemplateDeclaration *overroot; // first in overnext list 62 FuncDeclaration *funcroot; // first function in unified overload list 63 64 Dsymbol *onemember; // if !=NULL then one member of this template 65 66 bool literal; // this template declaration is a literal 67 bool ismixin; // template declaration is only to be used as a mixin 68 bool isstatic; // this is static template declaration 69 bool isTrivialAliasSeq; // matches `template AliasSeq(T...) { alias AliasSeq = T; } 70 bool isTrivialAlias; // matches pattern `template Alias(T) { alias Alias = qualifiers(T); }` 71 bool deprecated_; // this template declaration is deprecated 72 Visibility visibility; 73 int inuse; // for recursive expansion detection 74 75 TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack 76 77 TemplateDeclaration *syntaxCopy(Dsymbol *); 78 bool overloadInsert(Dsymbol *s); 79 bool hasStaticCtorOrDtor(); 80 const char *kind() const; 81 const char *toChars() const; 82 83 Visibility visible(); 84 85 MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs); 86 RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o); 87 isTemplateDeclaration()88 TemplateDeclaration *isTemplateDeclaration() { return this; } 89 90 TemplateTupleParameter *isVariadic(); 91 bool isDeprecated() const; 92 bool isOverloadable() const; 93 accept(Visitor * v)94 void accept(Visitor *v) { v->visit(this); } 95 }; 96 97 /* For type-parameter: 98 * template Foo(ident) // specType is set to NULL 99 * template Foo(ident : specType) 100 * For value-parameter: 101 * template Foo(valType ident) // specValue is set to NULL 102 * template Foo(valType ident : specValue) 103 * For alias-parameter: 104 * template Foo(alias ident) 105 * For this-parameter: 106 * template Foo(this ident) 107 */ 108 class TemplateParameter : public ASTNode 109 { 110 public: 111 Loc loc; 112 Identifier *ident; 113 114 /* True if this is a part of precedent parameter specialization pattern. 115 * 116 * template A(T : X!TL, alias X, TL...) {} 117 * // X and TL are dependent template parameter 118 * 119 * A dependent template parameter should return MATCHexact in matchArg() 120 * to respect the match level of the corresponding precedent parameter. 121 */ 122 bool dependent; 123 124 virtual TemplateTypeParameter *isTemplateTypeParameter(); 125 virtual TemplateValueParameter *isTemplateValueParameter(); 126 virtual TemplateAliasParameter *isTemplateAliasParameter(); 127 virtual TemplateThisParameter *isTemplateThisParameter(); 128 virtual TemplateTupleParameter *isTemplateTupleParameter(); 129 130 virtual TemplateParameter *syntaxCopy() = 0; 131 virtual bool declareParameter(Scope *sc) = 0; 132 virtual void print(RootObject *oarg, RootObject *oded) = 0; 133 virtual RootObject *specialization() = 0; 134 virtual RootObject *defaultArg(Loc instLoc, Scope *sc) = 0; 135 virtual bool hasDefaultArg() = 0; 136 137 /* Create dummy argument based on parameter. 138 */ 139 virtual RootObject *dummyArg() = 0; accept(Visitor * v)140 void accept(Visitor *v) { v->visit(this); } 141 }; 142 143 /* Syntax: 144 * ident : specType = defaultType 145 */ 146 class TemplateTypeParameter : public TemplateParameter 147 { 148 public: 149 Type *specType; // type parameter: if !=NULL, this is the type specialization 150 Type *defaultType; 151 152 TemplateTypeParameter *isTemplateTypeParameter(); 153 TemplateTypeParameter *syntaxCopy(); 154 bool declareParameter(Scope *sc); 155 void print(RootObject *oarg, RootObject *oded); 156 RootObject *specialization(); 157 RootObject *defaultArg(Loc instLoc, Scope *sc); 158 bool hasDefaultArg(); 159 RootObject *dummyArg(); accept(Visitor * v)160 void accept(Visitor *v) { v->visit(this); } 161 }; 162 163 /* Syntax: 164 * this ident : specType = defaultType 165 */ 166 class TemplateThisParameter : public TemplateTypeParameter 167 { 168 public: 169 TemplateThisParameter *isTemplateThisParameter(); 170 TemplateThisParameter *syntaxCopy(); accept(Visitor * v)171 void accept(Visitor *v) { v->visit(this); } 172 }; 173 174 /* Syntax: 175 * valType ident : specValue = defaultValue 176 */ 177 class TemplateValueParameter : public TemplateParameter 178 { 179 public: 180 Type *valType; 181 Expression *specValue; 182 Expression *defaultValue; 183 184 TemplateValueParameter *isTemplateValueParameter(); 185 TemplateValueParameter *syntaxCopy(); 186 bool declareParameter(Scope *sc); 187 void print(RootObject *oarg, RootObject *oded); 188 RootObject *specialization(); 189 RootObject *defaultArg(Loc instLoc, Scope *sc); 190 bool hasDefaultArg(); 191 RootObject *dummyArg(); accept(Visitor * v)192 void accept(Visitor *v) { v->visit(this); } 193 }; 194 195 /* Syntax: 196 * specType ident : specAlias = defaultAlias 197 */ 198 class TemplateAliasParameter : public TemplateParameter 199 { 200 public: 201 Type *specType; 202 RootObject *specAlias; 203 RootObject *defaultAlias; 204 205 TemplateAliasParameter *isTemplateAliasParameter(); 206 TemplateAliasParameter *syntaxCopy(); 207 bool declareParameter(Scope *sc); 208 void print(RootObject *oarg, RootObject *oded); 209 RootObject *specialization(); 210 RootObject *defaultArg(Loc instLoc, Scope *sc); 211 bool hasDefaultArg(); 212 RootObject *dummyArg(); accept(Visitor * v)213 void accept(Visitor *v) { v->visit(this); } 214 }; 215 216 /* Syntax: 217 * ident ... 218 */ 219 class TemplateTupleParameter : public TemplateParameter 220 { 221 public: 222 TemplateTupleParameter *isTemplateTupleParameter(); 223 TemplateTupleParameter *syntaxCopy(); 224 bool declareParameter(Scope *sc); 225 void print(RootObject *oarg, RootObject *oded); 226 RootObject *specialization(); 227 RootObject *defaultArg(Loc instLoc, Scope *sc); 228 bool hasDefaultArg(); 229 RootObject *dummyArg(); accept(Visitor * v)230 void accept(Visitor *v) { v->visit(this); } 231 }; 232 233 /* Given: 234 * foo!(args) => 235 * name = foo 236 * tiargs = args 237 */ 238 class TemplateInstance : public ScopeDsymbol 239 { 240 public: 241 Identifier *name; 242 243 // Array of Types/Expressions of template 244 // instance arguments [int*, char, 10*10] 245 Objects *tiargs; 246 247 // Array of Types/Expressions corresponding 248 // to TemplateDeclaration.parameters 249 // [int, char, 100] 250 Objects tdtypes; 251 252 // Modules imported by this template instance 253 Modules importedModules; 254 255 Dsymbol *tempdecl; // referenced by foo.bar.abc 256 Dsymbol *enclosing; // if referencing local symbols, this is the context 257 Dsymbol *aliasdecl; // !=NULL if instance is an alias for its sole member 258 TemplateInstance *inst; // refer to existing instance 259 ScopeDsymbol *argsym; // argument symbol table 260 hash_t hash; // cached result of toHash() 261 Expressions *fargs; // for function template, these are the function arguments 262 263 TemplateInstances* deferred; 264 265 Module *memberOf; // if !null, then this TemplateInstance appears in memberOf.members[] 266 267 // Used to determine the instance needs code generation. 268 // Note that these are inaccurate until semantic analysis phase completed. 269 TemplateInstance *tinst; // enclosing template instance 270 TemplateInstance *tnext; // non-first instantiated instances 271 Module *minst; // the top module that instantiated this instance 272 273 private: 274 unsigned short _nest; // for recursive pretty printing detection, 3 MSBs reserved for flags 275 public: 276 unsigned char inuse; // for recursive expansion detection 277 278 TemplateInstance *syntaxCopy(Dsymbol *); 279 Dsymbol *toAlias(); // resolve real symbol 280 const char *kind() const; 281 bool oneMember(Dsymbol **ps, Identifier *ident); 282 const char *toChars() const; 283 const char* toPrettyCharsHelper(); 284 Identifier *getIdent(); 285 hash_t toHash(); 286 287 bool needsCodegen(); 288 isTemplateInstance()289 TemplateInstance *isTemplateInstance() { return this; } accept(Visitor * v)290 void accept(Visitor *v) { v->visit(this); } 291 }; 292 293 class TemplateMixin : public TemplateInstance 294 { 295 public: 296 TypeQualified *tqual; 297 298 TemplateMixin *syntaxCopy(Dsymbol *s); 299 const char *kind() const; 300 bool oneMember(Dsymbol **ps, Identifier *ident); 301 bool hasPointers(); 302 void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion); 303 const char *toChars() const; 304 isTemplateMixin()305 TemplateMixin *isTemplateMixin() { return this; } accept(Visitor * v)306 void accept(Visitor *v) { v->visit(this); } 307 }; 308 309 Expression *isExpression(RootObject *o); 310 Dsymbol *isDsymbol(RootObject *o); 311 Type *isType(RootObject *o); 312 Tuple *isTuple(RootObject *o); 313 Parameter *isParameter(RootObject *o); 314 TemplateParameter *isTemplateParameter(RootObject *o); 315 bool isError(const RootObject *const o); 316