comparison dmd/GotoStatement.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.GotoStatement;
2
3 import dmd.Loc;
4 import dmd.Scope;
5 import dmd.Statement;
6 import dmd.Identifier;
7 import dmd.CompoundStatement;
8 import dmd.LabelDsymbol;
9 import dmd.TryFinallyStatement;
10 import dmd.FuncDeclaration;
11 import dmd.OutBuffer;
12 import dmd.HdrGenState;
13 import dmd.Expression;
14 import dmd.InterState;
15 import dmd.IRState;
16 import dmd.ArrayTypes;
17 import dmd.BE;
18
19 import dmd.codegen.Util;
20 import dmd.backend.Util;
21 import dmd.backend.block;
22 import dmd.backend.Blockx;
23 import dmd.backend.BC;
24
25 class GotoStatement : Statement
26 {
27 Identifier ident;
28 LabelDsymbol label = null;
29 TryFinallyStatement tf = null;
30
31 this(Loc loc, Identifier ident)
32 {
33 super(loc);
34 this.ident = ident;
35 }
36
37 Statement syntaxCopy()
38 {
39 GotoStatement s = new GotoStatement(loc, ident);
40 return s;
41 }
42
43 Statement semantic(Scope sc)
44 {
45 FuncDeclaration fd = sc.parent.isFuncDeclaration();
46
47 //printf("GotoStatement.semantic()\n");
48 tf = sc.tf;
49 label = fd.searchLabel(ident);
50 if (!label.statement && sc.fes)
51 {
52 /* Either the goto label is forward referenced or it
53 * is in the function that the enclosing foreach is in.
54 * Can't know yet, so wrap the goto in a compound statement
55 * so we can patch it later, and add it to a 'look at this later'
56 * list.
57 */
58 Statements a = new Statements();
59 Statement s;
60
61 a.push(cast(void*)this);
62 s = new CompoundStatement(loc, a);
63 sc.fes.gotos.push(cast(void*)s); // 'look at this later' list
64 return s;
65 }
66
67 if (label.statement && label.statement.tf != sc.tf)
68 error("cannot goto in or out of finally block");
69 return this;
70 }
71
72 BE blockExit()
73 {
74 //printf("GotoStatement.blockExit(%p)\n", this);
75 return BE.BEgoto;
76 }
77
78 Expression interpret(InterState* istate)
79 {
80 assert(false);
81 }
82
83 void toIR(IRState* irs)
84 {
85 block* b;
86 block* bdest;
87 Blockx* blx = irs.blx;
88
89 if (!label.statement)
90 {
91 error("label %s is undefined", label.toChars());
92 return;
93 }
94 if (tf !is label.statement.tf)
95 error("cannot goto forward out of or into finally block");
96
97 bdest = labelToBlock(loc, blx, label);
98 if (!bdest)
99 return;
100 b = blx.curblock;
101 incUsage(irs, loc);
102
103 // Adjust exception handler scope index if in different try blocks
104 if (b.Btry != bdest.Btry)
105 {
106 // Check that bdest is in an enclosing try block
107 for (block* bt = b.Btry; bt != bdest.Btry; bt = bt.Btry)
108 {
109 if (!bt)
110 {
111 //printf("b.Btry = %p, bdest.Btry = %p\n", b.Btry, bdest.Btry);
112 error("cannot goto into try block");
113 break;
114 }
115 }
116
117 //setScopeIndex(blx, b, bdest.Btry ? bdest.Btry.Bscope_index : -1);
118 }
119
120 list_append(&b.Bsucc,bdest);
121 block_next(blx,BCgoto,null);
122 }
123
124 void toCBuffer(OutBuffer buf, HdrGenState* hgs)
125 {
126 buf.writestring("goto ");
127 buf.writestring(ident.toChars());
128 buf.writebyte(';');
129 buf.writenl();
130 }
131
132 GotoStatement isGotoStatement() { return this; }
133 }