Home | History | Annotate | Line # | Download | only in dmd
      1 
      2 /* Compiler implementation of the D programming language
      3  * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved
      4  * written by Walter Bright
      5  * https://www.digitalmars.com
      6  * Distributed under the Boost Software License, Version 1.0.
      7  * https://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()
     37     DYNCAST dyncast() const { return DYNCAST_TUPLE; }
     38 
     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 
     88     TemplateDeclaration *isTemplateDeclaration() { return this; }
     89 
     90     TemplateTupleParameter *isVariadic();
     91     bool isDeprecated() const;
     92     bool isOverloadable() const;
     93 
     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(const Loc &instLoc, Scope *sc) = 0;
    135     virtual bool hasDefaultArg() = 0;
    136 
    137     /* Create dummy argument based on parameter.
    138      */
    139     virtual RootObject *dummyArg() = 0;
    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(const Loc &instLoc, Scope *sc);
    158     bool hasDefaultArg();
    159     RootObject *dummyArg();
    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();
    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(const Loc &instLoc, Scope *sc);
    190     bool hasDefaultArg();
    191     RootObject *dummyArg();
    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(const Loc &instLoc, Scope *sc);
    211     bool hasDefaultArg();
    212     RootObject *dummyArg();
    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(const Loc &instLoc, Scope *sc);
    228     bool hasDefaultArg();
    229     RootObject *dummyArg();
    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 isDiscardable();
    288     bool needsCodegen();
    289 
    290     TemplateInstance *isTemplateInstance() { return this; }
    291     void accept(Visitor *v) { v->visit(this); }
    292 };
    293 
    294 class TemplateMixin : public TemplateInstance
    295 {
    296 public:
    297     TypeQualified *tqual;
    298 
    299     TemplateMixin *syntaxCopy(Dsymbol *s);
    300     const char *kind() const;
    301     bool oneMember(Dsymbol **ps, Identifier *ident);
    302     bool hasPointers();
    303     void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion);
    304     const char *toChars() const;
    305 
    306     TemplateMixin *isTemplateMixin() { return this; }
    307     void accept(Visitor *v) { v->visit(this); }
    308 };
    309 
    310 Expression *isExpression(RootObject *o);
    311 Dsymbol *isDsymbol(RootObject *o);
    312 Type *isType(RootObject *o);
    313 Tuple *isTuple(RootObject *o);
    314 Parameter *isParameter(RootObject *o);
    315 TemplateParameter *isTemplateParameter(RootObject *o);
    316 bool isError(const RootObject *const o);
    317 void printTemplateStats();
    318