Mercurial > projects > ddmd
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 } |