Mercurial > projects > dil
comparison src/dil/ast/NodeCopier.d @ 806:bcb74c9b895c
Moved out files in the trunk folder to the root.
author | Aziz K?ksal <aziz.koeksal@gmail.com> |
---|---|
date | Sun, 09 Mar 2008 00:12:19 +0100 |
parents | trunk/src/dil/ast/NodeCopier.d@9e6c6bb73e5f |
children |
comparison
equal
deleted
inserted
replaced
805:a3fab8b74a7d | 806:bcb74c9b895c |
---|---|
1 /++ | |
2 Author: Aziz Köksal | |
3 License: GPL3 | |
4 +/ | |
5 module dil.ast.NodeCopier; | |
6 | |
7 import common; | |
8 | |
9 /// Mixed into the body of a class that inherits from Node. | |
10 const string copyMethod = ` | |
11 override typeof(this) copy() | |
12 { | |
13 mixin copyNode!(typeof(this)); | |
14 return copyNode(this); | |
15 }`; | |
16 | |
17 /// A helper function that generates code for copying subnodes. | |
18 string doCopy_(string obj, string[] members) | |
19 { | |
20 char[] result; | |
21 foreach (member; members) | |
22 { | |
23 if (member.length > 2 && member[$-2..$] == "[]") // Array copy. | |
24 { | |
25 member = member[0..$-2]; | |
26 // obj.member = obj.member.dup; | |
27 // foreach (ref m_; obj.member) | |
28 // m_ = m_.copy(); | |
29 result ~= obj~"."~member~" = "~obj~"."~member~".dup;" | |
30 "foreach (ref m_; "~obj~"."~member~")" | |
31 "m_ = m_.copy();"; | |
32 } | |
33 else if (member[$-1] == '?') // Optional member copy. | |
34 { | |
35 member = member[0..$-1]; | |
36 // obj.member && (obj.member = obj.member.copy()); | |
37 result ~= obj~"."~member~" && ("~obj~"."~member~" = "~obj~"."~member~".copy());"; | |
38 } | |
39 else // Non-optional member copy. | |
40 // obj.member = obj.member.copy(); | |
41 result ~= obj~"."~member~" = "~obj~"."~member~".copy();"; | |
42 } | |
43 return result; | |
44 } | |
45 | |
46 string doCopy(string[] members) | |
47 { | |
48 return doCopy_("x", members); | |
49 } | |
50 | |
51 string doCopy(string member) | |
52 { | |
53 return doCopy_("x", [member]); | |
54 } | |
55 | |
56 // pragma(msg, doCopy("decls?")); | |
57 | |
58 /// Returns a deep copy of node. | |
59 T copyNode(T)(T node) | |
60 { | |
61 assert(node !is null); | |
62 | |
63 // Firstly do a shallow copy. | |
64 T x = cast(T)cast(void*)node.dup; | |
65 | |
66 // Now copy the subnodes. | |
67 static if (is(Declaration) && is(T : Declaration)) | |
68 { | |
69 alias T D; | |
70 static if (is(D == CompoundDeclaration)) | |
71 mixin(doCopy("decls[]")); | |
72 //EmptyDeclaration, | |
73 //IllegalDeclaration, | |
74 //ModuleDeclaration have no subnodes. | |
75 static if (is(D == AliasDeclaration) || | |
76 is(D == TypedefDeclaration)) | |
77 mixin(doCopy("decl")); | |
78 static if (is(D == EnumDeclaration)) | |
79 mixin(doCopy(["baseType?", "members[]"])); | |
80 static if (is(D == EnumMemberDeclaration)) | |
81 mixin(doCopy("value")); | |
82 static if (is(D == ClassDeclaration) || is( D == InterfaceDeclaration)) | |
83 mixin(doCopy(["bases[]", "decls"])); | |
84 static if (is(D == StructDeclaration) || is(D == UnionDeclaration)) | |
85 mixin(doCopy("decls")); | |
86 static if (is(D == ConstructorDeclaration)) | |
87 mixin(doCopy(["params", "funcBody"])); | |
88 static if (is(D == StaticConstructorDeclaration) || | |
89 is(D == DestructorDeclaration) || | |
90 is(D == StaticDestructorDeclaration) || | |
91 is(D == InvariantDeclaration) || | |
92 is(D == UnittestDeclaration)) | |
93 mixin(doCopy("funcBody")); | |
94 static if (is(D == FunctionDeclaration)) | |
95 mixin(doCopy(["returnType", "params", "funcBody"])); | |
96 static if (is(D == VariablesDeclaration)) | |
97 { | |
98 mixin(doCopy("typeNode?")); | |
99 x.inits = x.inits.dup; | |
100 foreach(ref init; x.inits) | |
101 init && (init = init.copy()); | |
102 } | |
103 static if (is(D == DebugDeclaration) || is(D == VersionDeclaration)) | |
104 mixin(doCopy(["decls?","elseDecls?"])); | |
105 static if (is(D == StaticIfDeclaration)) | |
106 mixin(doCopy(["condition","ifDecls", "elseDecls?"])); | |
107 static if (is(D == StaticAssertDeclaration)) | |
108 mixin(doCopy(["condition","message?"])); | |
109 static if (is(D == TemplateDeclaration)) | |
110 mixin(doCopy(["tparams","decls"])); | |
111 static if (is(D == NewDeclaration) || is(D == DeleteDeclaration)) | |
112 mixin(doCopy(["params","funcBody"])); | |
113 static if (is(D == ProtectionDeclaration) || | |
114 is(D == StorageClassDeclaration) || | |
115 is(D == LinkageDeclaration) || | |
116 is(D == AlignDeclaration)) | |
117 mixin(doCopy("decls")); | |
118 static if (is(D == PragmaDeclaration)) | |
119 mixin(doCopy(["args[]","decls"])); | |
120 static if (is(D == MixinDeclaration)) | |
121 mixin(doCopy(["templateExpr?","argument?"])); | |
122 } | |
123 else | |
124 static if (is(Expression) && is(T : Expression)) | |
125 { | |
126 alias T E; | |
127 static if (is(E == IllegalExpression)) | |
128 {} | |
129 else | |
130 static if (is(E == CondExpression)) | |
131 mixin(doCopy(["condition", "lhs", "rhs"])); | |
132 else | |
133 static if (is(E : BinaryExpression)) | |
134 mixin(doCopy(["lhs", "rhs"])); | |
135 else | |
136 static if (is(E : UnaryExpression)) | |
137 { | |
138 static if (is(E == CastExpression)) | |
139 mixin(doCopy("type")); | |
140 mixin(doCopy("e")); // Copy member in base class UnaryExpression. | |
141 static if (is(E == IndexExpression)) | |
142 mixin(doCopy("args[]")); | |
143 static if (is(E == SliceExpression)) | |
144 mixin(doCopy(["left?", "right?"])); | |
145 static if (is(E == AsmPostBracketExpression)) | |
146 mixin(doCopy("e2")); | |
147 } | |
148 else | |
149 { | |
150 static if (is(E == NewExpression)) | |
151 mixin(doCopy(["newArgs[]", "type", "ctorArgs[]"])); | |
152 static if (is(E == NewAnonClassExpression)) | |
153 mixin(doCopy(["newArgs[]", "bases[]", "ctorArgs[]", "decls"])); | |
154 static if (is(E == AsmBracketExpression)) | |
155 mixin(doCopy("e")); | |
156 static if (is(E == TemplateInstanceExpression)) | |
157 mixin(doCopy("targs?")); | |
158 static if (is(E == ArrayLiteralExpression)) | |
159 mixin(doCopy("values[]")); | |
160 static if (is(E == AArrayLiteralExpression)) | |
161 mixin(doCopy(["keys[]", "values[]"])); | |
162 static if (is(E == AssertExpression)) | |
163 mixin(doCopy(["expr", "msg?"])); | |
164 static if (is(E == MixinExpression) || | |
165 is(E == ImportExpression)) | |
166 mixin(doCopy("expr")); | |
167 static if (is(E == TypeofExpression) || | |
168 is(E == TypeDotIdExpression) || | |
169 is(E == TypeidExpression)) | |
170 mixin(doCopy("type")); | |
171 static if (is(E == IsExpression)) | |
172 mixin(doCopy(["type", "specType?", "tparams?"])); | |
173 static if (is(E == FunctionLiteralExpression)) | |
174 mixin(doCopy(["returnType?", "params?", "funcBody"])); | |
175 static if (is(E == ParenExpression)) | |
176 mixin(doCopy("next")); | |
177 static if (is(E == TraitsExpression)) | |
178 mixin(doCopy("targs")); | |
179 // VoidInitializer has no subnodes. | |
180 static if (is(E == ArrayInitExpression)) | |
181 { | |
182 mixin(doCopy("values[]")); | |
183 x.keys = x.keys.dup; | |
184 foreach(ref key; x.keys) | |
185 key && (key = key.copy()); | |
186 } | |
187 static if (is(E == StructInitExpression)) | |
188 mixin(doCopy("values[]")); | |
189 static if (is(E == StringExpression)) | |
190 x.str = x.str.dup; | |
191 } | |
192 } | |
193 else | |
194 static if (is(Statement) && is(T : Statement)) | |
195 { | |
196 alias T S; | |
197 static if (is(S == CompoundStatement)) | |
198 mixin(doCopy("stmnts[]")); | |
199 //IllegalStatement, | |
200 //EmptyStatement have no subnodes. | |
201 static if (is(S == FuncBodyStatement)) | |
202 mixin(doCopy(["funcBody?", "inBody?", "outBody?"])); | |
203 static if (is(S == ScopeStatement) || is(S == LabeledStatement)) | |
204 mixin(doCopy("s")); | |
205 static if (is(S == ExpressionStatement)) | |
206 mixin(doCopy("e")); | |
207 static if (is(S == DeclarationStatement)) | |
208 mixin(doCopy("decl")); | |
209 static if (is(S == IfStatement)) | |
210 { | |
211 if (x.variable) | |
212 mixin(doCopy("variable")); | |
213 else | |
214 mixin(doCopy("condition")); | |
215 mixin(doCopy(["ifBody", "elseBody?"])); | |
216 } | |
217 static if (is(S == WhileStatement)) | |
218 mixin(doCopy(["condition", "whileBody"])); | |
219 static if (is(S == DoWhileStatement)) | |
220 mixin(doCopy(["doBody", "condition"])); | |
221 static if (is(S == ForStatement)) | |
222 mixin(doCopy(["init?", "condition?", "increment?", "forBody"])); | |
223 static if (is(S == ForeachStatement)) | |
224 mixin(doCopy(["params", "aggregate", "forBody"])); | |
225 static if (is(S == ForeachRangeStatement)) | |
226 mixin(doCopy(["params", "lower", "upper", "forBody"])); | |
227 static if (is(S == SwitchStatement)) | |
228 mixin(doCopy(["condition", "switchBody"])); | |
229 static if (is(S == CaseStatement)) | |
230 mixin(doCopy(["values[]", "caseBody"])); | |
231 static if (is(S == DefaultStatement)) | |
232 mixin(doCopy("defaultBody")); | |
233 //ContinueStatement, | |
234 //BreakStatement have no subnodes. | |
235 static if (is(S == ReturnStatement)) | |
236 mixin(doCopy("e?")); | |
237 static if (is(S == GotoStatement)) | |
238 mixin(doCopy("caseExpr?")); | |
239 static if (is(S == WithStatement)) | |
240 mixin(doCopy(["e", "withBody"])); | |
241 static if (is(S == SynchronizedStatement)) | |
242 mixin(doCopy(["e?", "syncBody"])); | |
243 static if (is(S == TryStatement)) | |
244 mixin(doCopy(["tryBody", "catchBodies[]", "finallyBody?"])); | |
245 static if (is(S == CatchStatement)) | |
246 mixin(doCopy(["param?", "catchBody"])); | |
247 static if (is(S == FinallyStatement)) | |
248 mixin(doCopy("finallyBody")); | |
249 static if (is(S == ScopeGuardStatement)) | |
250 mixin(doCopy("scopeBody")); | |
251 static if (is(S == ThrowStatement)) | |
252 mixin(doCopy("e")); | |
253 static if (is(S == VolatileStatement)) | |
254 mixin(doCopy("volatileBody?")); | |
255 static if (is(S == AsmBlockStatement)) | |
256 mixin(doCopy("statements")); | |
257 static if (is(S == AsmStatement)) | |
258 mixin(doCopy("operands[]")); | |
259 //AsmAlignStatement, | |
260 //IllegalAsmStatement have no subnodes. | |
261 static if (is(S == PragmaStatement)) | |
262 mixin(doCopy(["args[]", "pragmaBody"])); | |
263 static if (is(S == MixinStatement)) | |
264 mixin(doCopy("templateExpr")); | |
265 static if (is(S == StaticIfStatement)) | |
266 mixin(doCopy(["condition", "ifBody", "elseBody?"])); | |
267 static if (is(S == StaticAssertStatement)) | |
268 mixin(doCopy(["condition", "message?"])); | |
269 static if (is(S == DebugStatement) || is(S == VersionStatement)) | |
270 mixin(doCopy(["mainBody", "elseBody?"])); | |
271 } | |
272 else | |
273 static if (is(TypeNode) && is(T : TypeNode)) | |
274 { | |
275 //IllegalType, | |
276 //IntegralType, | |
277 //ModuleScopeType, | |
278 //IdentifierType have no subnodes. | |
279 static if (is(T == QualifiedType)) | |
280 mixin(doCopy(["lhs", "rhs"])); | |
281 static if (is(T == TypeofType)) | |
282 mixin(doCopy("e")); | |
283 static if (is(T == TemplateInstanceType)) | |
284 mixin(doCopy("targs?")); | |
285 static if (is(T == PointerType)) | |
286 mixin(doCopy("next")); | |
287 static if (is(T == ArrayType)) | |
288 mixin(doCopy(["next", "assocType?", "e1?", "e2?"])); | |
289 static if (is(T == FunctionType) || is(T == DelegateType)) | |
290 mixin(doCopy(["returnType", "params"])); | |
291 static if (is(T == CFuncPointerType)) | |
292 mixin(doCopy(["next", "params?"])); | |
293 static if (is(T == BaseClassType) || | |
294 is(T == ConstType) || | |
295 is(T == InvariantType)) | |
296 mixin(doCopy("next")); | |
297 } | |
298 else | |
299 static if (is(Parameter) && is(T == Parameter)) | |
300 { | |
301 mixin(doCopy(["type?", "defValue?"])); | |
302 } | |
303 else | |
304 static if (is(Parameter) && is(T == Parameters) || | |
305 is(TemplateParameter) && is(T == TemplateParameters) || | |
306 is(TemplateArguments) && is(T == TemplateArguments)) | |
307 { | |
308 mixin(doCopy("children[]")); | |
309 } | |
310 else | |
311 static if (is(TemplateParameter) && is(T : TemplateParameter)) | |
312 { | |
313 static if (is(N == TemplateAliasParameter) || | |
314 is(N == TemplateTypeParameter) || | |
315 is(N == TemplateThisParameter)) | |
316 mixin(doCopy(["specType", "defType"])); | |
317 static if (is(N == TemplateValueParameter)) | |
318 mixin(doCopy(["valueType", "specValue?", "defValue?"])); | |
319 //TemplateTupleParameter has no subnodes. | |
320 } | |
321 else | |
322 static assert(0, "copying of "~typeof(x).stringof~" is not handled"); | |
323 return x; | |
324 } |