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