Mercurial > projects > ddmd
comparison dmd/CaseStatement.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | a8b50ff7f201 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
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 { | |
47 assert(false); | |
48 } | |
49 | |
50 Statement semantic(Scope sc) | |
51 { | |
52 SwitchStatement sw = sc.sw; | |
53 | |
54 //printf("CaseStatement.semantic() %s\n", toChars()); | |
55 exp = exp.semantic(sc); | |
56 if (sw) | |
57 { | |
58 exp = exp.implicitCastTo(sc, sw.condition.type); | |
59 exp = exp.optimize(WANTvalue | WANTinterpret); | |
60 | |
61 /* This is where variables are allowed as case expressions. | |
62 */ | |
63 if (exp.op == TOKvar) | |
64 { VarExp ve = cast(VarExp)exp; | |
65 VarDeclaration v = ve.var.isVarDeclaration(); | |
66 Type t = exp.type.toBasetype(); | |
67 if (v && (t.isintegral() || t.ty == Tclass)) | |
68 { | |
69 /* Flag that we need to do special code generation | |
70 * for this, i.e. generate a sequence of if-then-else | |
71 */ | |
72 sw.hasVars = 1; | |
73 if (sw.isFinal) | |
74 error("case variables not allowed in final switch statements"); | |
75 goto L1; | |
76 } | |
77 } | |
78 | |
79 if (exp.op != TOKstring && exp.op != TOKint64) | |
80 { | |
81 error("case must be a string or an integral constant, not %s", exp.toChars()); | |
82 exp = new IntegerExp(0); | |
83 } | |
84 | |
85 L1: | |
86 for (int i = 0; i < sw.cases.dim; i++) | |
87 { | |
88 CaseStatement cs = cast(CaseStatement)sw.cases.data[i]; | |
89 | |
90 //printf("comparing '%s' with '%s'\n", exp.toChars(), cs.exp.toChars()); | |
91 if (cs.exp.equals(exp)) | |
92 { | |
93 error("duplicate case %s in switch statement", exp.toChars()); | |
94 break; | |
95 } | |
96 } | |
97 | |
98 sw.cases.push(cast(void*)this); | |
99 | |
100 // Resolve any goto case's with no exp to this case statement | |
101 for (int i = 0; i < sw.gotoCases.dim; i++) | |
102 { | |
103 GotoCaseStatement gcs = cast(GotoCaseStatement)sw.gotoCases.data[i]; | |
104 | |
105 if (!gcs.exp) | |
106 { | |
107 gcs.cs = this; | |
108 sw.gotoCases.remove(i); // remove from array | |
109 } | |
110 } | |
111 | |
112 if (sc.sw.tf !is sc.tf) | |
113 error("switch and case are in different finally blocks"); | |
114 } | |
115 else | |
116 error("case not in switch statement"); | |
117 statement = statement.semantic(sc); | |
118 return this; | |
119 } | |
120 | |
121 int compare(Object obj) | |
122 { | |
123 assert(false); | |
124 } | |
125 | |
126 bool usesEH() | |
127 { | |
128 assert(false); | |
129 } | |
130 | |
131 BE blockExit() | |
132 { | |
133 return statement.blockExit(); | |
134 } | |
135 | |
136 bool comeFrom() | |
137 { | |
138 return true; | |
139 } | |
140 | |
141 Expression interpret(InterState *istate) | |
142 { | |
143 assert(false); | |
144 } | |
145 | |
146 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
147 { | |
148 assert(false); | |
149 } | |
150 | |
151 Statement inlineScan(InlineScanState* iss) | |
152 { | |
153 //printf("CaseStatement.inlineScan()\n"); | |
154 exp = exp.inlineScan(iss); | |
155 if (statement) | |
156 statement = statement.inlineScan(iss); | |
157 return this; | |
158 } | |
159 | |
160 void toIR(IRState *irs) | |
161 { | |
162 Blockx* blx = irs.blx; | |
163 block* bcase = blx.curblock; | |
164 if (!cblock) | |
165 cblock = block_calloc(blx); | |
166 block_next(blx,BCgoto,cblock); | |
167 block* bsw = irs.getSwitchBlock(); | |
168 if (bsw.BC == BCswitch) | |
169 list_append(&bsw.Bsucc,cblock); // second entry in pair | |
170 list_append(&bcase.Bsucc,cblock); | |
171 if (blx.tryblock != bsw.Btry) | |
172 error("case cannot be in different try block level from switch"); | |
173 incUsage(irs, loc); | |
174 if (statement) | |
175 statement.toIR(irs); | |
176 } | |
177 } |