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 }