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