1
/**
2
 * Semantic analysis of template parameters.
3
 *
4
 * Copyright:   Copyright (C) 1999-2020 by The D Language Foundation, All Rights Reserved
5
 * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
6
 * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7
 * Source:      $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/templateparamsem.d, _templateparamsem.d)
8
 * Documentation:  https://dlang.org/phobos/dmd_templateparamsem.html
9
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/templateparamsem.d
10
 */
11

12
module dmd.templateparamsem;
13

14
import dmd.arraytypes;
15
import dmd.dsymbol;
16
import dmd.dscope;
17
import dmd.dtemplate;
18
import dmd.globals;
19
import dmd.expression;
20
import dmd.expressionsem;
21
import dmd.root.rootobject;
22
import dmd.mtype;
23
import dmd.typesem;
24
import dmd.visitor;
25

26
/************************************************
27
 * Performs semantic on TemplateParameter AST nodes.
28
 *
29
 * Params:
30
 *      tp = element of `parameters` to be semantically analyzed
31
 *      sc = context
32
 *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
33
 * Returns:
34
 *      `true` if no errors
35
 */
36
extern(C++) bool tpsemantic(TemplateParameter tp, Scope* sc, TemplateParameters* parameters)
37
{
38 1
    scope v = new TemplateParameterSemanticVisitor(sc, parameters);
39 1
    tp.accept(v);
40 1
    return v.result;
41
}
42

43

44
private extern (C++) final class TemplateParameterSemanticVisitor : Visitor
45
{
46
    alias visit = Visitor.visit;
47

48
    Scope* sc;
49
    TemplateParameters* parameters;
50
    bool result;
51

52 1
    this(Scope* sc, TemplateParameters* parameters)
53
    {
54 1
        this.sc = sc;
55 1
        this.parameters = parameters;
56
    }
57

58
    override void visit(TemplateTypeParameter ttp)
59
    {
60
        //printf("TemplateTypeParameter.semantic('%s')\n", ident.toChars());
61 1
        if (ttp.specType && !reliesOnTident(ttp.specType, parameters))
62
        {
63 1
            ttp.specType = ttp.specType.typeSemantic(ttp.loc, sc);
64
        }
65
        version (none)
66
        {
67
            // Don't do semantic() until instantiation
68
            if (ttp.defaultType)
69
            {
70
                ttp.defaultType = ttp.defaultType.typeSemantic(ttp.loc, sc);
71
            }
72
        }
73 1
        result = !(ttp.specType && isError(ttp.specType));
74
    }
75

76
    override void visit(TemplateValueParameter tvp)
77
    {
78 1
        tvp.valType = tvp.valType.typeSemantic(tvp.loc, sc);
79
        version (none)
80
        {
81
            // defer semantic analysis to arg match
82
            if (tvp.specValue)
83
            {
84
                Expression e = tvp.specValue;
85
                sc = sc.startCTFE();
86
                e = e.semantic(sc);
87
                sc = sc.endCTFE();
88
                e = e.implicitCastTo(sc, tvp.valType);
89
                e = e.ctfeInterpret();
90
                if (e.op == TOK.int64 || e.op == TOK.float64 ||
91
                    e.op == TOK.complex80 || e.op == TOK.null_ || e.op == TOK.string_)
92
                    tvp.specValue = e;
93
            }
94

95
            if (tvp.defaultValue)
96
            {
97
                Expression e = defaultValue;
98
                sc = sc.startCTFE();
99
                e = e.semantic(sc);
100
                sc = sc.endCTFE();
101
                e = e.implicitCastTo(sc, tvp.valType);
102
                e = e.ctfeInterpret();
103
                if (e.op == TOK.int64)
104
                    tvp.defaultValue = e;
105
            }
106
        }
107 1
        result = !isError(tvp.valType);
108
    }
109

110
    override void visit(TemplateAliasParameter tap)
111
    {
112 1
        if (tap.specType && !reliesOnTident(tap.specType, parameters))
113
        {
114 1
            tap.specType = tap.specType.typeSemantic(tap.loc, sc);
115
        }
116 1
        tap.specAlias = aliasParameterSemantic(tap.loc, sc, tap.specAlias, parameters);
117
        version (none)
118
        {
119
            // Don't do semantic() until instantiation
120
            if (tap.defaultAlias)
121
                tap.defaultAlias = tap.defaultAlias.semantic(tap.loc, sc);
122
        }
123 1
        result = !(tap.specType && isError(tap.specType)) && !(tap.specAlias && isError(tap.specAlias));
124
    }
125

126
    override void visit(TemplateTupleParameter ttp)
127
    {
128 1
        result = true;
129
    }
130
}
131

132
/***********************************************
133
 * Support function for performing semantic analysis on `TemplateAliasParameter`.
134
 *
135
 * Params:
136
 *      loc = location (for error messages)
137
 *      sc = context
138
 *      o = object to run semantic() on, the `TemplateAliasParameter`s `specAlias` or `defaultAlias`
139
 *      parameters = array of `TemplateParameters` supplied to the `TemplateDeclaration`
140
 * Returns:
141
 *      object resulting from running `semantic` on `o`
142
 */
143
RootObject aliasParameterSemantic(Loc loc, Scope* sc, RootObject o, TemplateParameters* parameters)
144
{
145 1
    if (o)
146
    {
147 1
        Expression ea = isExpression(o);
148 1
        Type ta = isType(o);
149 1
        if (ta && (!parameters || !reliesOnTident(ta, parameters)))
150
        {
151 1
            Dsymbol s = ta.toDsymbol(sc);
152 1
            if (s)
153 1
                o = s;
154
            else
155 0
                o = ta.typeSemantic(loc, sc);
156
        }
157 1
        else if (ea)
158
        {
159 1
            sc = sc.startCTFE();
160 1
            ea = ea.expressionSemantic(sc);
161 1
            sc = sc.endCTFE();
162 1
            o = ea.ctfeInterpret();
163
        }
164
    }
165 1
    return o;
166
}

Read our documentation on viewing source code .

Loading