Mercurial > projects > ddmd
comparison dmd/BreakStatement.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.BreakStatement; | |
2 | |
3 import dmd.Statement; | |
4 import dmd.Loc; | |
5 import dmd.Identifier; | |
6 import dmd.Scope; | |
7 import dmd.Expression; | |
8 import dmd.InterState; | |
9 import dmd.OutBuffer; | |
10 import dmd.HdrGenState; | |
11 import dmd.IRState; | |
12 import dmd.BE; | |
13 import dmd.FuncDeclaration; | |
14 import dmd.LabelStatement; | |
15 import dmd.ReturnStatement; | |
16 import dmd.IntegerExp; | |
17 | |
18 import dmd.backend.Util; | |
19 import dmd.backend.block; | |
20 import dmd.backend.Blockx; | |
21 import dmd.backend.BC; | |
22 | |
23 class BreakStatement : Statement | |
24 { | |
25 Identifier ident; | |
26 | |
27 this(Loc loc, Identifier ident) | |
28 { | |
29 super(loc); | |
30 this.ident = ident; | |
31 } | |
32 | |
33 Statement syntaxCopy() | |
34 { | |
35 assert(false); | |
36 } | |
37 | |
38 Statement semantic(Scope sc) | |
39 { | |
40 //printf("BreakStatement::semantic()\n"); | |
41 // If: | |
42 // break Identifier; | |
43 if (ident) | |
44 { | |
45 Scope scx; | |
46 FuncDeclaration thisfunc = sc.func; | |
47 | |
48 for (scx = sc; scx; scx = scx.enclosing) | |
49 { | |
50 LabelStatement ls; | |
51 | |
52 if (scx.func != thisfunc) // if in enclosing function | |
53 { | |
54 if (sc.fes) // if this is the body of a foreach | |
55 { | |
56 /* Post this statement to the fes, and replace | |
57 * it with a return value that caller will put into | |
58 * a switch. Caller will figure out where the break | |
59 * label actually is. | |
60 * Case numbers start with 2, not 0, as 0 is continue | |
61 * and 1 is break. | |
62 */ | |
63 Statement s; | |
64 sc.fes.cases.push(cast(void*)this); | |
65 s = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1)); | |
66 return s; | |
67 } | |
68 break; // can't break to it | |
69 } | |
70 | |
71 ls = scx.slabel; | |
72 if (ls && ls.ident == ident) | |
73 { | |
74 Statement s = ls.statement; | |
75 | |
76 if (!s.hasBreak()) | |
77 error("label '%s' has no break", ident.toChars()); | |
78 if (ls.tf != sc.tf) | |
79 error("cannot break out of finally block"); | |
80 return this; | |
81 } | |
82 } | |
83 error("enclosing label '%s' for break not found", ident.toChars()); | |
84 } | |
85 else if (!sc.sbreak) | |
86 { | |
87 if (sc.fes) | |
88 { | |
89 Statement s; | |
90 | |
91 // Replace break; with return 1; | |
92 s = new ReturnStatement(Loc(0), new IntegerExp(1)); | |
93 return s; | |
94 } | |
95 error("break is not inside a loop or switch"); | |
96 } | |
97 return this; | |
98 } | |
99 | |
100 Expression interpret(InterState* istate) | |
101 { | |
102 assert(false); | |
103 } | |
104 | |
105 BE blockExit() | |
106 { | |
107 //printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak); | |
108 return ident ? BE.BEgoto : BE.BEbreak; | |
109 } | |
110 | |
111 void toCBuffer(OutBuffer buf, HdrGenState* hgs) | |
112 { | |
113 assert(false); | |
114 } | |
115 | |
116 void toIR(IRState* irs) | |
117 { | |
118 block* bbreak; | |
119 block* b; | |
120 Blockx* blx = irs.blx; | |
121 | |
122 bbreak = irs.getBreakBlock(ident); | |
123 assert(bbreak); | |
124 b = blx.curblock; | |
125 incUsage(irs, loc); | |
126 | |
127 // Adjust exception handler scope index if in different try blocks | |
128 if (b.Btry != bbreak.Btry) | |
129 { | |
130 //setScopeIndex(blx, b, bbreak.Btry ? bbreak.Btry.Bscope_index : -1); | |
131 } | |
132 | |
133 /* Nothing more than a 'goto' to the current break destination | |
134 */ | |
135 list_append(&b.Bsucc, bbreak); | |
136 block_next(blx, BCgoto, null); | |
137 } | |
138 } |