1
/**
2
 * Used to help transform statement AST into flow graph.
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/stmtstate.d, _stmtstate.d)
8
 * Documentation: https://dlang.org/phobos/dmd_stmtstate.html
9
 * Coverage:    https://codecov.io/gh/dlang/dmd/src/master/src/dmd/stmtstate.d
10
 */
11

12
module dmd.stmtstate;
13

14
import dmd.identifier;
15
import dmd.statement;
16

17

18
/************************************************
19
 * Used to traverse the statement AST to transform it into
20
 * a flow graph.
21
 * Keeps track of things like "where does the `break` go".
22
 * Params:
23
 *      block = type of the flow graph node
24
 */
25
struct StmtState(block)
26
{
27
    StmtState* prev;
28
    Statement statement;
29

30
    Identifier ident;
31
    block* breakBlock;
32
    block* contBlock;
33
    block* switchBlock;
34
    block* defaultBlock;
35
    block* finallyBlock;
36
    block* tryBlock;
37

38 1
    this(StmtState* prev, Statement statement)
39
    {
40 1
        this.prev = prev;
41 1
        this.statement = statement;
42 1
        if (prev)
43 1
            this.tryBlock = prev.tryBlock;
44
    }
45

46
    block* getBreakBlock(Identifier ident)
47
    {
48 1
        StmtState* bc;
49 1
        if (ident)
50
        {
51 1
            Statement related = null;
52 1
            block* ret = null;
53 1
            for (bc = &this; bc; bc = bc.prev)
54
            {
55
                // The label for a breakBlock may actually be some levels up (e.g.
56
                // on a try/finally wrapping a loop). We'll see if this breakBlock
57
                // is the one to return once we reach that outer statement (which
58
                // in many cases will be this same statement).
59 1
                if (bc.breakBlock)
60
                {
61 1
                    related = bc.statement.getRelatedLabeled();
62 1
                    ret = bc.breakBlock;
63
                }
64 1
                if (bc.statement == related && bc.prev.ident == ident)
65 1
                    return ret;
66
            }
67
        }
68
        else
69
        {
70 1
            for (bc = &this; bc; bc = bc.prev)
71
            {
72 1
                if (bc.breakBlock)
73 1
                    return bc.breakBlock;
74
            }
75
        }
76 0
        return null;
77
    }
78

79
    block* getContBlock(Identifier ident)
80
    {
81 1
        StmtState* bc;
82 1
        if (ident)
83
        {
84 1
            block* ret = null;
85 1
            for (bc = &this; bc; bc = bc.prev)
86
            {
87
                // The label for a contBlock may actually be some levels up (e.g.
88
                // on a try/finally wrapping a loop). We'll see if this contBlock
89
                // is the one to return once we reach that outer statement (which
90
                // in many cases will be this same statement).
91 1
                if (bc.contBlock)
92
                {
93 1
                    ret = bc.contBlock;
94
                }
95 1
                if (bc.prev && bc.prev.ident == ident)
96 1
                    return ret;
97
            }
98
        }
99
        else
100
        {
101 1
            for (bc = &this; bc; bc = bc.prev)
102
            {
103 1
                if (bc.contBlock)
104 1
                    return bc.contBlock;
105
            }
106
        }
107 0
        return null;
108
    }
109

110
    block* getSwitchBlock()
111
    {
112 1
        StmtState* bc;
113 1
        for (bc = &this; bc; bc = bc.prev)
114
        {
115 1
            if (bc.switchBlock)
116 1
                return bc.switchBlock;
117
        }
118 0
        return null;
119
    }
120

121
    block* getDefaultBlock()
122
    {
123 1
        StmtState* bc;
124 1
        for (bc = &this; bc; bc = bc.prev)
125
        {
126 1
            if (bc.defaultBlock)
127 1
                return bc.defaultBlock;
128
        }
129 0
        return null;
130
    }
131

132
    block* getFinallyBlock()
133
    {
134 0
        StmtState* bc;
135 0
        for (bc = &this; bc; bc = bc.prev)
136
        {
137 0
            if (bc.finallyBlock)
138 0
                return bc.finallyBlock;
139
        }
140 0
        return null;
141
    }
142
}

Read our documentation on viewing source code .

Loading