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