1 2 /* Compiler implementation of the D programming language 3 * Copyright (C) 1999-2019 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 "root/root.h" 14 #include "arraytypes.h" 15 #include "dsymbol.h" 16 17 18 struct OutBuffer; 19 class Identifier; 20 class TemplateInstance; 21 class TemplateParameter; 22 class TemplateTypeParameter; 23 class TemplateThisParameter; 24 class TemplateValueParameter; 25 class TemplateAliasParameter; 26 class TemplateTupleParameter; 27 class Type; 28 class TypeQualified; 29 class TypeTypeof; 30 struct Scope; 31 class Expression; 32 class AliasDeclaration; 33 class FuncDeclaration; 34 class Parameter; 35 enum MATCH; 36 enum PASS; 37 38 class Tuple : public RootObject 39 { 40 public: 41 Objects objects; 42 43 // kludge for template.isType() dyncast()44 int dyncast() const { return DYNCAST_TUPLE; } 45 toChars()46 const char *toChars() { return objects.toChars(); } 47 }; 48 49 struct TemplatePrevious 50 { 51 TemplatePrevious *prev; 52 Scope *sc; 53 Objects *dedargs; 54 }; 55 56 class TemplateDeclaration : public ScopeDsymbol 57 { 58 public: 59 TemplateParameters *parameters; // array of TemplateParameter's 60 61 TemplateParameters *origParameters; // originals for Ddoc 62 Expression *constraint; 63 64 // Hash table to look up TemplateInstance's of this TemplateDeclaration 65 void *instances; 66 67 TemplateDeclaration *overnext; // next overloaded TemplateDeclaration 68 TemplateDeclaration *overroot; // first in overnext list 69 FuncDeclaration *funcroot; // first function in unified overload list 70 71 Dsymbol *onemember; // if !=NULL then one member of this template 72 73 bool literal; // this template declaration is a literal 74 bool ismixin; // template declaration is only to be used as a mixin 75 bool isstatic; // this is static template declaration 76 Prot protection; 77 78 TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack 79 80 TemplateDeclaration(Loc loc, Identifier *id, TemplateParameters *parameters, 81 Expression *constraint, Dsymbols *decldefs, bool ismixin = false, bool literal = false); 82 Dsymbol *syntaxCopy(Dsymbol *); 83 void semantic(Scope *sc); 84 bool overloadInsert(Dsymbol *s); 85 bool hasStaticCtorOrDtor(); 86 const char *kind() const; 87 const char *toChars(); 88 89 Prot prot(); 90 91 bool evaluateConstraint(TemplateInstance *ti, Scope *sc, Scope *paramscope, Objects *dedtypes, FuncDeclaration *fd); 92 93 MATCH matchWithInstance(Scope *sc, TemplateInstance *ti, Objects *atypes, Expressions *fargs, int flag); 94 MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs); 95 96 MATCH deduceFunctionTemplateMatch(TemplateInstance *ti, Scope *sc, FuncDeclaration *&fd, Type *tthis, Expressions *fargs); 97 RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o); 98 FuncDeclaration *doHeaderInstantiation(TemplateInstance *ti, Scope *sc, FuncDeclaration *fd, Type *tthis, Expressions *fargs); 99 TemplateInstance *findExistingInstance(TemplateInstance *tithis, Expressions *fargs); 100 TemplateInstance *addInstance(TemplateInstance *ti); 101 void removeInstance(TemplateInstance *handle); 102 isTemplateDeclaration()103 TemplateDeclaration *isTemplateDeclaration() { return this; } 104 105 TemplateTupleParameter *isVariadic(); 106 bool isOverloadable(); 107 accept(Visitor * v)108 void accept(Visitor *v) { v->visit(this); } 109 }; 110 111 /* For type-parameter: 112 * template Foo(ident) // specType is set to NULL 113 * template Foo(ident : specType) 114 * For value-parameter: 115 * template Foo(valType ident) // specValue is set to NULL 116 * template Foo(valType ident : specValue) 117 * For alias-parameter: 118 * template Foo(alias ident) 119 * For this-parameter: 120 * template Foo(this ident) 121 */ 122 class TemplateParameter 123 { 124 public: 125 Loc loc; 126 Identifier *ident; 127 128 /* True if this is a part of precedent parameter specialization pattern. 129 * 130 * template A(T : X!TL, alias X, TL...) {} 131 * // X and TL are dependent template parameter 132 * 133 * A dependent template parameter should return MATCHexact in matchArg() 134 * to respect the match level of the corresponding precedent parameter. 135 */ 136 bool dependent; 137 138 TemplateParameter(Loc loc, Identifier *ident); 139 140 virtual TemplateTypeParameter *isTemplateTypeParameter(); 141 virtual TemplateValueParameter *isTemplateValueParameter(); 142 virtual TemplateAliasParameter *isTemplateAliasParameter(); 143 virtual TemplateThisParameter *isTemplateThisParameter(); 144 virtual TemplateTupleParameter *isTemplateTupleParameter(); 145 146 virtual TemplateParameter *syntaxCopy() = 0; 147 virtual bool declareParameter(Scope *sc) = 0; 148 virtual bool semantic(Scope *sc, TemplateParameters *parameters) = 0; 149 virtual void print(RootObject *oarg, RootObject *oded) = 0; 150 virtual RootObject *specialization() = 0; 151 virtual RootObject *defaultArg(Loc instLoc, Scope *sc) = 0; 152 virtual bool hasDefaultArg() = 0; 153 154 /* Match actual argument against parameter. 155 */ 156 virtual MATCH matchArg(Loc instLoc, Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); 157 virtual MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam) = 0; 158 159 /* Create dummy argument based on parameter. 160 */ 161 virtual void *dummyArg() = 0; accept(Visitor * v)162 virtual void accept(Visitor *v) { v->visit(this); } 163 }; 164 165 /* Syntax: 166 * ident : specType = defaultType 167 */ 168 class TemplateTypeParameter : public TemplateParameter 169 { 170 using TemplateParameter::matchArg; 171 public: 172 Type *specType; // type parameter: if !=NULL, this is the type specialization 173 Type *defaultType; 174 175 static Type *tdummy; 176 177 TemplateTypeParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); 178 179 TemplateTypeParameter *isTemplateTypeParameter(); 180 TemplateParameter *syntaxCopy(); 181 bool declareParameter(Scope *sc); 182 bool semantic(Scope *sc, TemplateParameters *parameters); 183 void print(RootObject *oarg, RootObject *oded); 184 RootObject *specialization(); 185 RootObject *defaultArg(Loc instLoc, Scope *sc); 186 bool hasDefaultArg(); 187 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); 188 void *dummyArg(); accept(Visitor * v)189 void accept(Visitor *v) { v->visit(this); } 190 }; 191 192 /* Syntax: 193 * this ident : specType = defaultType 194 */ 195 class TemplateThisParameter : public TemplateTypeParameter 196 { 197 public: 198 TemplateThisParameter(Loc loc, Identifier *ident, Type *specType, Type *defaultType); 199 200 TemplateThisParameter *isTemplateThisParameter(); 201 TemplateParameter *syntaxCopy(); accept(Visitor * v)202 void accept(Visitor *v) { v->visit(this); } 203 }; 204 205 /* Syntax: 206 * valType ident : specValue = defaultValue 207 */ 208 class TemplateValueParameter : public TemplateParameter 209 { 210 using TemplateParameter::matchArg; 211 public: 212 Type *valType; 213 Expression *specValue; 214 Expression *defaultValue; 215 216 static AA *edummies; 217 218 TemplateValueParameter(Loc loc, Identifier *ident, Type *valType, Expression *specValue, Expression *defaultValue); 219 220 TemplateValueParameter *isTemplateValueParameter(); 221 TemplateParameter *syntaxCopy(); 222 bool declareParameter(Scope *sc); 223 bool semantic(Scope *sc, TemplateParameters *parameters); 224 void print(RootObject *oarg, RootObject *oded); 225 RootObject *specialization(); 226 RootObject *defaultArg(Loc instLoc, Scope *sc); 227 bool hasDefaultArg(); 228 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); 229 void *dummyArg(); accept(Visitor * v)230 void accept(Visitor *v) { v->visit(this); } 231 }; 232 233 /* Syntax: 234 * specType ident : specAlias = defaultAlias 235 */ 236 class TemplateAliasParameter : public TemplateParameter 237 { 238 using TemplateParameter::matchArg; 239 public: 240 Type *specType; 241 RootObject *specAlias; 242 RootObject *defaultAlias; 243 244 static Dsymbol *sdummy; 245 246 TemplateAliasParameter(Loc loc, Identifier *ident, Type *specType, RootObject *specAlias, RootObject *defaultAlias); 247 248 TemplateAliasParameter *isTemplateAliasParameter(); 249 TemplateParameter *syntaxCopy(); 250 bool declareParameter(Scope *sc); 251 bool semantic(Scope *sc, TemplateParameters *parameters); 252 void print(RootObject *oarg, RootObject *oded); 253 RootObject *specialization(); 254 RootObject *defaultArg(Loc instLoc, Scope *sc); 255 bool hasDefaultArg(); 256 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); 257 void *dummyArg(); accept(Visitor * v)258 void accept(Visitor *v) { v->visit(this); } 259 }; 260 261 /* Syntax: 262 * ident ... 263 */ 264 class TemplateTupleParameter : public TemplateParameter 265 { 266 public: 267 TemplateTupleParameter(Loc loc, Identifier *ident); 268 269 TemplateTupleParameter *isTemplateTupleParameter(); 270 TemplateParameter *syntaxCopy(); 271 bool declareParameter(Scope *sc); 272 bool semantic(Scope *sc, TemplateParameters *parameters); 273 void print(RootObject *oarg, RootObject *oded); 274 RootObject *specialization(); 275 RootObject *defaultArg(Loc instLoc, Scope *sc); 276 bool hasDefaultArg(); 277 MATCH matchArg(Loc loc, Scope *sc, Objects *tiargs, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); 278 MATCH matchArg(Scope *sc, RootObject *oarg, size_t i, TemplateParameters *parameters, Objects *dedtypes, Declaration **psparam); 279 void *dummyArg(); accept(Visitor * v)280 void accept(Visitor *v) { v->visit(this); } 281 }; 282 283 /* Given: 284 * foo!(args) => 285 * name = foo 286 * tiargs = args 287 */ 288 class TemplateInstance : public ScopeDsymbol 289 { 290 public: 291 Identifier *name; 292 293 // Array of Types/Expressions of template 294 // instance arguments [int*, char, 10*10] 295 Objects *tiargs; 296 297 // Array of Types/Expressions corresponding 298 // to TemplateDeclaration.parameters 299 // [int, char, 100] 300 Objects tdtypes; 301 302 Dsymbol *tempdecl; // referenced by foo.bar.abc 303 Dsymbol *enclosing; // if referencing local symbols, this is the context 304 Dsymbol *aliasdecl; // !=NULL if instance is an alias for its sole member 305 TemplateInstance *inst; // refer to existing instance 306 ScopeDsymbol *argsym; // argument symbol table 307 int inuse; // for recursive expansion detection 308 int nest; // for recursive pretty printing detection 309 bool semantictiargsdone; // has semanticTiargs() been done? 310 bool havetempdecl; // if used second constructor 311 bool gagged; // if the instantiation is done with error gagging 312 hash_t hash; // cached result of toHash() 313 Expressions *fargs; // for function template, these are the function arguments 314 315 TemplateInstances* deferred; 316 317 Module *memberOf; // if !null, then this TemplateInstance appears in memberOf.members[] 318 319 // Used to determine the instance needs code generation. 320 // Note that these are inaccurate until semantic analysis phase completed. 321 TemplateInstance *tinst; // enclosing template instance 322 TemplateInstance *tnext; // non-first instantiated instances 323 Module *minst; // the top module that instantiated this instance 324 325 TemplateInstance(Loc loc, Identifier *temp_id); 326 TemplateInstance(Loc loc, TemplateDeclaration *tempdecl, Objects *tiargs); 327 static Objects *arraySyntaxCopy(Objects *objs); 328 Dsymbol *syntaxCopy(Dsymbol *); 329 void semantic(Scope *sc, Expressions *fargs); 330 void semantic(Scope *sc); 331 void semantic2(Scope *sc); 332 void semantic3(Scope *sc); 333 Dsymbol *toAlias(); // resolve real symbol 334 const char *kind() const; 335 bool oneMember(Dsymbol **ps, Identifier *ident); 336 const char *toChars(); 337 const char* toPrettyCharsHelper(); 338 void printInstantiationTrace(); 339 Identifier *getIdent(); 340 int compare(RootObject *o); 341 hash_t toHash(); 342 343 bool needsCodegen(); 344 345 // Internal 346 bool findTempDecl(Scope *sc, WithScopeSymbol **pwithsym); 347 bool updateTempDecl(Scope *sc, Dsymbol *s); 348 static bool semanticTiargs(Loc loc, Scope *sc, Objects *tiargs, int flags); 349 bool semanticTiargs(Scope *sc); 350 bool findBestMatch(Scope *sc, Expressions *fargs); 351 bool needsTypeInference(Scope *sc, int flag = 0); 352 bool hasNestedArgs(Objects *tiargs, bool isstatic); 353 Dsymbols *appendToModuleMember(); 354 void declareParameters(Scope *sc); 355 Identifier *genIdent(Objects *args); 356 void expandMembers(Scope *sc); 357 void tryExpandMembers(Scope *sc); 358 void trySemantic3(Scope *sc2); 359 isTemplateInstance()360 TemplateInstance *isTemplateInstance() { return this; } accept(Visitor * v)361 void accept(Visitor *v) { v->visit(this); } 362 }; 363 364 class TemplateMixin : public TemplateInstance 365 { 366 public: 367 TypeQualified *tqual; 368 369 TemplateMixin(Loc loc, Identifier *ident, TypeQualified *tqual, Objects *tiargs); 370 Dsymbol *syntaxCopy(Dsymbol *s); 371 void semantic(Scope *sc); 372 void semantic2(Scope *sc); 373 void semantic3(Scope *sc); 374 const char *kind() const; 375 bool oneMember(Dsymbol **ps, Identifier *ident); 376 int apply(Dsymbol_apply_ft_t fp, void *param); 377 bool hasPointers(); 378 void setFieldOffset(AggregateDeclaration *ad, unsigned *poffset, bool isunion); 379 const char *toChars(); 380 381 bool findTempDecl(Scope *sc); 382 isTemplateMixin()383 TemplateMixin *isTemplateMixin() { return this; } accept(Visitor * v)384 void accept(Visitor *v) { v->visit(this); } 385 }; 386 387 Expression *isExpression(RootObject *o); 388 Dsymbol *isDsymbol(RootObject *o); 389 Type *isType(RootObject *o); 390 Tuple *isTuple(RootObject *o); 391 Parameter *isParameter(RootObject *o); 392 bool arrayObjectIsError(Objects *args); 393 bool isError(RootObject *o); 394 Type *getType(RootObject *o); 395 Dsymbol *getDsymbol(RootObject *o); 396 397 RootObject *objectSyntaxCopy(RootObject *o); 398