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