annotate dmd/CaseStatement.d @ 178:e3afd1303184

Many small bugs fixed Made all classes derive from TObject to detect memory leaks (functionality is disabled for now) Began work on overriding backend memory allocations (to avoid memory leaks)
author korDen
date Sun, 17 Oct 2010 07:42:00 +0400
parents af724d3510d7
children b0d41ff5e0df
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
1 module dmd.CaseStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
2
114
e28b18c23469 added a module dmd.common for commonly used stuff
Trass3r
parents: 72
diff changeset
3 import dmd.common;
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
4 import dmd.Statement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
5 import dmd.Expression;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
6 import dmd.Statement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
7 import dmd.Scope;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
8 import dmd.Loc;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
9 import dmd.IRState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
10 import dmd.InlineScanState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
11 import dmd.HdrGenState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
12 import dmd.OutBuffer;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
13 import dmd.InterState;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
14 import dmd.BE;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
15 import dmd.SwitchStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
16 import dmd.WANT;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
17 import dmd.TOK;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
18 import dmd.VarExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
19 import dmd.VarDeclaration;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
20 import dmd.Type;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
21 import dmd.TY;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
22 import dmd.IntegerExp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
23 import dmd.GotoCaseStatement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
24
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
25 import dmd.backend.block;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
26 import dmd.backend.Blockx;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
27 import dmd.backend.Util;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
28 import dmd.backend.BC;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
29
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
30 class CaseStatement : Statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
31 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
32 Expression exp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
33 Statement statement;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
34
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
35 int index = 0; // which case it is (since we sort this)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
36 block* cblock = null; // back end: label for the block
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
37
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
38 this(Loc loc, Expression exp, Statement s)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
39 {
178
e3afd1303184 Many small bugs fixed
korDen
parents: 174
diff changeset
40 register();
e3afd1303184 Many small bugs fixed
korDen
parents: 174
diff changeset
41
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
42 super(loc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
43
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
44 this.exp = exp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
45 this.statement = s;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
46 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
47
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
48 override Statement syntaxCopy()
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
49 {
53
a8b50ff7f201 ForeachStatement.syntaxCopy
korDen
parents: 0
diff changeset
50 CaseStatement s = new CaseStatement(loc, exp.syntaxCopy(), statement.syntaxCopy());
a8b50ff7f201 ForeachStatement.syntaxCopy
korDen
parents: 0
diff changeset
51 return s;
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
52 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
53
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
54 override Statement semantic(Scope sc)
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
55 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
56 SwitchStatement sw = sc.sw;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
57
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
58 //printf("CaseStatement.semantic() %s\n", toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
59 exp = exp.semantic(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
60 if (sw)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
61 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
62 exp = exp.implicitCastTo(sc, sw.condition.type);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
63 exp = exp.optimize(WANTvalue | WANTinterpret);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
64
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
65 /* This is where variables are allowed as case expressions.
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
66 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
67 if (exp.op == TOKvar)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
68 { VarExp ve = cast(VarExp)exp;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
69 VarDeclaration v = ve.var.isVarDeclaration();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
70 Type t = exp.type.toBasetype();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
71 if (v && (t.isintegral() || t.ty == Tclass))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
72 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
73 /* Flag that we need to do special code generation
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
74 * for this, i.e. generate a sequence of if-then-else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
75 */
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
76 sw.hasVars = 1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
77 if (sw.isFinal)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
78 error("case variables not allowed in final switch statements");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
79 goto L1;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
80 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
81 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
82
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
83 if (exp.op != TOKstring && exp.op != TOKint64)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
84 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
85 error("case must be a string or an integral constant, not %s", exp.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
86 exp = new IntegerExp(0);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
87 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
88
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
89 L1:
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
90 for (int i = 0; i < sw.cases.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
91 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
92 CaseStatement cs = cast(CaseStatement)sw.cases.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
93
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
94 //printf("comparing '%s' with '%s'\n", exp.toChars(), cs.exp.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
95 if (cs.exp.equals(exp))
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
96 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
97 error("duplicate case %s in switch statement", exp.toChars());
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
98 break;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
99 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
100 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
101
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
102 sw.cases.push(cast(void*)this);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
103
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
104 // Resolve any goto case's with no exp to this case statement
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
105 for (int i = 0; i < sw.gotoCases.dim; i++)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
106 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
107 GotoCaseStatement gcs = cast(GotoCaseStatement)sw.gotoCases.data[i];
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
108
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
109 if (!gcs.exp)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
110 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
111 gcs.cs = this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
112 sw.gotoCases.remove(i); // remove from array
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
113 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
114 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
115
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
116 if (sc.sw.tf !is sc.tf)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
117 error("switch and case are in different finally blocks");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
118 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
119 else
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
120 error("case not in switch statement");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
121 statement = statement.semantic(sc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
122 return this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
123 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
124
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
125 override int opCmp(Object obj)
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
126 {
68
ee3a9f34dc48 final bits of codegen implementation to compile Phobos
korDen
parents: 63
diff changeset
127 // Sort cases so we can do an efficient lookup
ee3a9f34dc48 final bits of codegen implementation to compile Phobos
korDen
parents: 63
diff changeset
128 CaseStatement cs2 = cast(CaseStatement)obj;
ee3a9f34dc48 final bits of codegen implementation to compile Phobos
korDen
parents: 63
diff changeset
129
ee3a9f34dc48 final bits of codegen implementation to compile Phobos
korDen
parents: 63
diff changeset
130 return exp.opCmp(cs2.exp);
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
131 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
132
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
133 override bool usesEH()
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
134 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
135 assert(false);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
136 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
137
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
138 override BE blockExit()
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
139 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
140 return statement.blockExit();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
141 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
142
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
143 override bool comeFrom()
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
144 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
145 return true;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
146 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
147
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
148 override Expression interpret(InterState istate)
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
149 {
163
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
150 version (LOG) {
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
151 printf("CaseStatement.interpret(%s) this = %p\n", exp.toChars(), this);
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
152 }
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
153 if (istate.start is this)
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
154 istate.start = null;
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
155 if (statement)
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
156 return statement.interpret(istate);
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
157 else
fe932c1a9563 *.interpret functions implemenation
korDen
parents: 114
diff changeset
158 return null;
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
159 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
160
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
161 override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
162 {
174
af724d3510d7 lot os toCBuffer methods implemented
korDen
parents: 163
diff changeset
163 buf.writestring("case ");
af724d3510d7 lot os toCBuffer methods implemented
korDen
parents: 163
diff changeset
164 exp.toCBuffer(buf, hgs);
af724d3510d7 lot os toCBuffer methods implemented
korDen
parents: 163
diff changeset
165 buf.writebyte(':');
af724d3510d7 lot os toCBuffer methods implemented
korDen
parents: 163
diff changeset
166 buf.writenl();
af724d3510d7 lot os toCBuffer methods implemented
korDen
parents: 163
diff changeset
167 statement.toCBuffer(buf, hgs);
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
168 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
169
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
170 override Statement inlineScan(InlineScanState* iss)
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
171 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
172 //printf("CaseStatement.inlineScan()\n");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
173 exp = exp.inlineScan(iss);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
174 if (statement)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
175 statement = statement.inlineScan(iss);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
176 return this;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
177 }
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
178
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
179 override void toIR(IRState *irs)
0
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
180 {
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
181 Blockx* blx = irs.blx;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
182 block* bcase = blx.curblock;
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
183 if (!cblock)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
184 cblock = block_calloc(blx);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
185 block_next(blx,BCgoto,cblock);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
186 block* bsw = irs.getSwitchBlock();
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
187 if (bsw.BC == BCswitch)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
188 list_append(&bsw.Bsucc,cblock); // second entry in pair
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
189 list_append(&bcase.Bsucc,cblock);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
190 if (blx.tryblock != bsw.Btry)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
191 error("case cannot be in different try block level from switch");
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
192 incUsage(irs, loc);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
193 if (statement)
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
194 statement.toIR(irs);
10317f0c89a5 Initial commit
korDen
parents:
diff changeset
195 }
72
2e2a5c3f943a reduced warnings by adding override to the methods
Trass3r
parents: 68
diff changeset
196 }