| |
| /* Compiler implementation of the D programming language |
| * Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved |
| * written by Walter Bright |
| * https://www.digitalmars.com |
| * Distributed under the Boost Software License, Version 1.0. |
| * https://www.boost.org/LICENSE_1_0.txt |
| * https://github.com/dlang/dmd/blob/master/src/dmd/template.h |
| */ |
| |
| #pragma once |
| |
| #include "arraytypes.h" |
| #include "dsymbol.h" |
| |
| class Identifier; |
| class TemplateInstance; |
| class TemplateParameter; |
| class TemplateTypeParameter; |
| class TemplateThisParameter; |
| class TemplateValueParameter; |
| class TemplateAliasParameter; |
| class TemplateTupleParameter; |
| class Type; |
| class TypeQualified; |
| struct Scope; |
| class Expression; |
| class FuncDeclaration; |
| class Parameter; |
| |
| class Tuple final : public RootObject |
| { |
| public: |
| Objects objects; |
| |
| // kludge for template.isType() |
| DYNCAST dyncast() const override { return DYNCAST_TUPLE; } |
| |
| const char *toChars() const override { return objects.toChars(); } |
| }; |
| |
| struct TemplatePrevious |
| { |
| TemplatePrevious *prev; |
| Scope *sc; |
| Objects *dedargs; |
| }; |
| |
| class TemplateDeclaration final : public ScopeDsymbol |
| { |
| public: |
| TemplateParameters *parameters; // array of TemplateParameter's |
| |
| TemplateParameters *origParameters; // originals for Ddoc |
| Expression *constraint; |
| |
| // Hash table to look up TemplateInstance's of this TemplateDeclaration |
| void *instances; |
| |
| TemplateDeclaration *overnext; // next overloaded TemplateDeclaration |
| TemplateDeclaration *overroot; // first in overnext list |
| FuncDeclaration *funcroot; // first function in unified overload list |
| |
| Dsymbol *onemember; // if !=NULL then one member of this template |
| |
| bool literal; // this template declaration is a literal |
| bool ismixin; // template declaration is only to be used as a mixin |
| bool isstatic; // this is static template declaration |
| bool isTrivialAliasSeq; // matches `template AliasSeq(T...) { alias AliasSeq = T; } |
| bool isTrivialAlias; // matches pattern `template Alias(T) { alias Alias = qualifiers(T); }` |
| bool deprecated_; // this template declaration is deprecated |
| Visibility visibility; |
| int inuse; // for recursive expansion detection |
| |
| TemplatePrevious *previous; // threaded list of previous instantiation attempts on stack |
| |
| TemplateDeclaration *syntaxCopy(Dsymbol *) override; |
| bool overloadInsert(Dsymbol *s) override; |
| bool hasStaticCtorOrDtor() override; |
| const char *kind() const override; |
| const char *toChars() const override; |
| |
| Visibility visible() override; |
| |
| MATCH leastAsSpecialized(Scope *sc, TemplateDeclaration *td2, Expressions *fargs); |
| RootObject *declareParameter(Scope *sc, TemplateParameter *tp, RootObject *o); |
| |
| TemplateDeclaration *isTemplateDeclaration() override { return this; } |
| |
| TemplateTupleParameter *isVariadic(); |
| bool isDeprecated() const override; |
| bool isOverloadable() const override; |
| |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* 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) |
| */ |
| class TemplateParameter : public ASTNode |
| { |
| public: |
| Loc loc; |
| Identifier *ident; |
| |
| /* True if this is a part of precedent parameter specialization pattern. |
| * |
| * template A(T : X!TL, alias X, TL...) {} |
| * // X and TL are dependent template parameter |
| * |
| * A dependent template parameter should return MATCHexact in matchArg() |
| * to respect the match level of the corresponding precedent parameter. |
| */ |
| bool dependent; |
| |
| virtual TemplateTypeParameter *isTemplateTypeParameter(); |
| virtual TemplateValueParameter *isTemplateValueParameter(); |
| virtual TemplateAliasParameter *isTemplateAliasParameter(); |
| virtual TemplateThisParameter *isTemplateThisParameter(); |
| virtual TemplateTupleParameter *isTemplateTupleParameter(); |
| |
| virtual TemplateParameter *syntaxCopy() = 0; |
| virtual bool declareParameter(Scope *sc) = 0; |
| virtual void print(RootObject *oarg, RootObject *oded) = 0; |
| virtual RootObject *specialization() = 0; |
| virtual RootObject *defaultArg(const Loc &instLoc, Scope *sc) = 0; |
| virtual bool hasDefaultArg() = 0; |
| |
| DYNCAST dyncast() const override { return DYNCAST_TEMPLATEPARAMETER; } |
| |
| /* Create dummy argument based on parameter. |
| */ |
| virtual RootObject *dummyArg() = 0; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* Syntax: |
| * ident : specType = defaultType |
| */ |
| class TemplateTypeParameter : public TemplateParameter |
| { |
| public: |
| Type *specType; // type parameter: if !=NULL, this is the type specialization |
| Type *defaultType; |
| |
| TemplateTypeParameter *isTemplateTypeParameter() override final; |
| TemplateTypeParameter *syntaxCopy() override; |
| bool declareParameter(Scope *sc) override final; |
| void print(RootObject *oarg, RootObject *oded) override final; |
| RootObject *specialization() override final; |
| RootObject *defaultArg(const Loc &instLoc, Scope *sc) override final; |
| bool hasDefaultArg() override final; |
| RootObject *dummyArg() override final; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* Syntax: |
| * this ident : specType = defaultType |
| */ |
| class TemplateThisParameter final : public TemplateTypeParameter |
| { |
| public: |
| TemplateThisParameter *isTemplateThisParameter() override; |
| TemplateThisParameter *syntaxCopy() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* Syntax: |
| * valType ident : specValue = defaultValue |
| */ |
| class TemplateValueParameter final : public TemplateParameter |
| { |
| public: |
| Type *valType; |
| Expression *specValue; |
| Expression *defaultValue; |
| |
| TemplateValueParameter *isTemplateValueParameter() override; |
| TemplateValueParameter *syntaxCopy() override; |
| bool declareParameter(Scope *sc) override; |
| void print(RootObject *oarg, RootObject *oded) override; |
| RootObject *specialization() override; |
| RootObject *defaultArg(const Loc &instLoc, Scope *sc) override; |
| bool hasDefaultArg() override; |
| RootObject *dummyArg() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* Syntax: |
| * specType ident : specAlias = defaultAlias |
| */ |
| class TemplateAliasParameter final : public TemplateParameter |
| { |
| public: |
| Type *specType; |
| RootObject *specAlias; |
| RootObject *defaultAlias; |
| |
| TemplateAliasParameter *isTemplateAliasParameter() override; |
| TemplateAliasParameter *syntaxCopy() override; |
| bool declareParameter(Scope *sc) override; |
| void print(RootObject *oarg, RootObject *oded) override; |
| RootObject *specialization() override; |
| RootObject *defaultArg(const Loc &instLoc, Scope *sc) override; |
| bool hasDefaultArg() override; |
| RootObject *dummyArg() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* Syntax: |
| * ident ... |
| */ |
| class TemplateTupleParameter final : public TemplateParameter |
| { |
| public: |
| TemplateTupleParameter *isTemplateTupleParameter() override; |
| TemplateTupleParameter *syntaxCopy() override; |
| bool declareParameter(Scope *sc) override; |
| void print(RootObject *oarg, RootObject *oded) override; |
| RootObject *specialization() override; |
| RootObject *defaultArg(const Loc &instLoc, Scope *sc) override; |
| bool hasDefaultArg() override; |
| RootObject *dummyArg() override; |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| /* Given: |
| * foo!(args) => |
| * name = foo |
| * tiargs = args |
| */ |
| class TemplateInstance : public ScopeDsymbol |
| { |
| public: |
| Identifier *name; |
| |
| // Array of Types/Expressions of template |
| // instance arguments [int*, char, 10*10] |
| Objects *tiargs; |
| |
| // Array of Types/Expressions corresponding |
| // to TemplateDeclaration.parameters |
| // [int, char, 100] |
| Objects tdtypes; |
| |
| // Modules imported by this template instance |
| Modules importedModules; |
| |
| Dsymbol *tempdecl; // referenced by foo.bar.abc |
| Dsymbol *enclosing; // if referencing local symbols, this is the context |
| Dsymbol *aliasdecl; // !=NULL if instance is an alias for its sole member |
| TemplateInstance *inst; // refer to existing instance |
| ScopeDsymbol *argsym; // argument symbol table |
| hash_t hash; // cached result of toHash() |
| Expressions *fargs; // for function template, these are the function arguments |
| |
| TemplateInstances* deferred; |
| |
| Module *memberOf; // if !null, then this TemplateInstance appears in memberOf.members[] |
| |
| // Used to determine the instance needs code generation. |
| // Note that these are inaccurate until semantic analysis phase completed. |
| TemplateInstance *tinst; // enclosing template instance |
| TemplateInstance *tnext; // non-first instantiated instances |
| Module *minst; // the top module that instantiated this instance |
| |
| private: |
| unsigned short _nest; // for recursive pretty printing detection, 3 MSBs reserved for flags |
| public: |
| unsigned char inuse; // for recursive expansion detection |
| |
| TemplateInstance *syntaxCopy(Dsymbol *) override; |
| Dsymbol *toAlias() override final; // resolve real symbol |
| const char *kind() const override; |
| bool oneMember(Dsymbol **ps, Identifier *ident) override; |
| const char *toChars() const override; |
| const char* toPrettyCharsHelper() override final; |
| Identifier *getIdent() override final; |
| hash_t toHash(); |
| |
| bool isDiscardable(); |
| bool needsCodegen(); |
| |
| TemplateInstance *isTemplateInstance() override final { return this; } |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| class TemplateMixin final : public TemplateInstance |
| { |
| public: |
| TypeQualified *tqual; |
| |
| TemplateMixin *syntaxCopy(Dsymbol *s) override; |
| const char *kind() const override; |
| bool oneMember(Dsymbol **ps, Identifier *ident) override; |
| bool hasPointers() override; |
| void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override; |
| const char *toChars() const override; |
| |
| TemplateMixin *isTemplateMixin() override { return this; } |
| void accept(Visitor *v) override { v->visit(this); } |
| }; |
| |
| Expression *isExpression(RootObject *o); |
| Dsymbol *isDsymbol(RootObject *o); |
| Type *isType(RootObject *o); |
| Tuple *isTuple(RootObject *o); |
| Parameter *isParameter(RootObject *o); |
| TemplateParameter *isTemplateParameter(RootObject *o); |
| bool isError(const RootObject *const o); |
| void printTemplateStats(); |