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 }