Mercurial > projects > ddmd
comparison dmd/TryCatchStatement.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | cab4c37afb89 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.TryCatchStatement; | |
2 | |
3 import dmd.Statement; | |
4 import dmd.Array; | |
5 import dmd.Loc; | |
6 import dmd.Id; | |
7 import dmd.Identifier; | |
8 import dmd.Scope; | |
9 import dmd.InlineScanState; | |
10 import dmd.IRState; | |
11 import dmd.OutBuffer; | |
12 import dmd.Catch; | |
13 import dmd.HdrGenState; | |
14 import dmd.BE; | |
15 | |
16 import dmd.backend.BC; | |
17 import dmd.codegen.Util; | |
18 import dmd.backend.Util; | |
19 import dmd.backend.Blockx; | |
20 import dmd.backend.block; | |
21 import dmd.backend.mTY; | |
22 import dmd.backend.TYM; | |
23 | |
24 class TryCatchStatement : Statement | |
25 { | |
26 Statement body_; | |
27 Array catches; | |
28 | |
29 this(Loc loc, Statement body_, Array catches) | |
30 { | |
31 super(loc); | |
32 this.body_ = body_; | |
33 this.catches = catches; | |
34 } | |
35 | |
36 Statement syntaxCopy() | |
37 { | |
38 assert(false); | |
39 } | |
40 | |
41 Statement semantic(Scope sc) | |
42 { | |
43 body_ = body_.semanticScope(sc, null /*this*/, null); | |
44 | |
45 /* Even if body is null, still do semantic analysis on catches | |
46 */ | |
47 for (size_t i = 0; i < catches.dim; i++) | |
48 { | |
49 Catch c = cast(Catch)catches.data[i]; | |
50 c.semantic(sc); | |
51 | |
52 // Determine if current catch 'hides' any previous catches | |
53 for (size_t j = 0; j < i; j++) | |
54 { | |
55 Catch cj = cast(Catch)catches.data[j]; | |
56 string si = c.loc.toChars(); | |
57 string sj = cj.loc.toChars(); | |
58 | |
59 if (c.type.toBasetype().implicitConvTo(cj.type.toBasetype())) | |
60 error("catch at %s hides catch at %s", sj, si); | |
61 } | |
62 } | |
63 | |
64 if (!body_ || body_.isEmpty()) | |
65 { | |
66 return null; | |
67 } | |
68 return this; | |
69 } | |
70 | |
71 bool hasBreak() | |
72 { | |
73 assert(false); | |
74 } | |
75 | |
76 bool usesEH() | |
77 { | |
78 assert(false); | |
79 } | |
80 | |
81 BE blockExit() | |
82 { | |
83 assert(body_); | |
84 BE result = body_.blockExit(); | |
85 | |
86 BE catchresult = BE.BEnone; | |
87 for (size_t i = 0; i < catches.dim; i++) | |
88 { | |
89 Catch c = cast(Catch)catches.data[i]; | |
90 catchresult |= c.blockExit(); | |
91 | |
92 /* If we're catching Object, then there is no throwing | |
93 */ | |
94 Identifier id = c.type.toBasetype().isClassHandle().ident; | |
95 if (i == 0 && | |
96 (id is Id.Object_ || id is Id.Throwable || id is Id.Exception)) | |
97 { | |
98 result &= ~BE.BEthrow; | |
99 } | |
100 } | |
101 return result | catchresult; | |
102 } | |
103 | |
104 Statement inlineScan(InlineScanState* iss) | |
105 { | |
106 if (body_) | |
107 body_ = body_.inlineScan(iss); | |
108 if (catches) | |
109 { | |
110 for (int i = 0; i < catches.dim; i++) | |
111 { | |
112 Catch c = cast(Catch)catches.data[i]; | |
113 | |
114 if (c.handler) | |
115 c.handler = c.handler.inlineScan(iss); | |
116 } | |
117 } | |
118 return this; | |
119 } | |
120 | |
121 /*************************************** | |
122 * Builds the following: | |
123 * _try | |
124 * block | |
125 * jcatch | |
126 * handler | |
127 * A try-catch statement. | |
128 */ | |
129 void toIR(IRState *irs) | |
130 { | |
131 Blockx *blx = irs.blx; | |
132 | |
133 version (SEH) { | |
134 nteh_declarvars(blx); | |
135 } | |
136 | |
137 IRState mystate = IRState(irs, this); | |
138 | |
139 block* tryblock = block_goto(blx,BCgoto,null); | |
140 | |
141 int previndex = blx.scope_index; | |
142 tryblock.Blast_index = previndex; | |
143 blx.scope_index = tryblock.Bscope_index = blx.next_index++; | |
144 | |
145 // Set the current scope index | |
146 setScopeIndex(blx,tryblock,tryblock.Bscope_index); | |
147 | |
148 // This is the catch variable | |
149 tryblock.jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr)); | |
150 | |
151 blx.tryblock = tryblock; | |
152 block *breakblock = block_calloc(blx); | |
153 block_goto(blx,BC_try,null); | |
154 if (body_) | |
155 { | |
156 body_.toIR(&mystate); | |
157 } | |
158 blx.tryblock = tryblock.Btry; | |
159 | |
160 // break block goes here | |
161 block_goto(blx, BCgoto, breakblock); | |
162 | |
163 setScopeIndex(blx,blx.curblock, previndex); | |
164 blx.scope_index = previndex; | |
165 | |
166 // create new break block that follows all the catches | |
167 breakblock = block_calloc(blx); | |
168 | |
169 list_append(&blx.curblock.Bsucc, breakblock); | |
170 block_next(blx,BCgoto,null); | |
171 | |
172 assert(catches); | |
173 for (int i = 0 ; i < catches.dim; i++) | |
174 { | |
175 Catch cs = cast(Catch)(catches.data[i]); | |
176 if (cs.var) | |
177 cs.var.csym = tryblock.jcatchvar; | |
178 block* bcatch = blx.curblock; | |
179 if (cs.type) | |
180 bcatch.Bcatchtype = cs.type.toBasetype().toSymbol(); | |
181 list_append(&tryblock.Bsucc,bcatch); | |
182 block_goto(blx,BCjcatch,null); | |
183 if (cs.handler !is null) | |
184 { | |
185 IRState catchState = IRState(irs, this); | |
186 cs.handler.toIR(&catchState); | |
187 } | |
188 list_append(&blx.curblock.Bsucc, breakblock); | |
189 block_next(blx, BCgoto, null); | |
190 } | |
191 | |
192 block_next(blx,cast(BC)blx.curblock.BC, breakblock); | |
193 } | |
194 | |
195 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
196 { | |
197 assert(false); | |
198 } | |
199 | |
200 TryCatchStatement isTryCatchStatement() { return this; } | |
201 } |