Mercurial > projects > ddmd
comparison dmd/expression/Cat.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 7427ded8caf7 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:10317f0c89a5 |
---|---|
1 module dmd.expression.Cat; | |
2 | |
3 import dmd.Type; | |
4 import dmd.Expression; | |
5 import dmd.Loc; | |
6 import dmd.TOK; | |
7 import dmd.StringExp; | |
8 import dmd.ArrayLiteralExp; | |
9 import dmd.Global; | |
10 import dmd.TY; | |
11 import dmd.Type; | |
12 import dmd.GlobalExpressions; | |
13 import dmd.ArrayTypes; | |
14 import dmd.TypeSArray; | |
15 import dmd.IntegerExp; | |
16 | |
17 import core.stdc.string; | |
18 import core.stdc.stdlib; | |
19 | |
20 import std.contracts; | |
21 | |
22 /* Also return EXP_CANT_INTERPRET if this fails | |
23 */ | |
24 Expression Cat(Type type, Expression e1, Expression e2) | |
25 { | |
26 Expression e = EXP_CANT_INTERPRET; | |
27 Loc loc = e1.loc; | |
28 | |
29 Type t; | |
30 | |
31 Type t1 = e1.type.toBasetype(); | |
32 Type t2 = e2.type.toBasetype(); | |
33 | |
34 //printf("Cat(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars()); | |
35 //printf("\tt1 = %s, t2 = %s\n", t1.toChars(), t2.toChars()); | |
36 | |
37 if (e1.op == TOKnull && (e2.op == TOKint64 || e2.op == TOKstructliteral)) | |
38 { | |
39 e = e2; | |
40 goto L2; | |
41 } | |
42 else if ((e1.op == TOKint64 || e1.op == TOKstructliteral) && e2.op == TOKnull) | |
43 { | |
44 e = e1; | |
45 L2: | |
46 Type tn = e.type.toBasetype(); | |
47 if (tn.ty == Tchar || tn.ty == Twchar || tn.ty == Tdchar) | |
48 { | |
49 // Create a StringExp | |
50 size_t len = 1; | |
51 int sz = cast(int)tn.size(); | |
52 ulong v = e.toInteger(); | |
53 | |
54 char* s = cast(char*)malloc((len + 1) * sz); | |
55 memcpy(s, &v, sz); | |
56 | |
57 // Add terminating 0 | |
58 memset(s + len * sz, 0, sz); | |
59 | |
60 StringExp es = new StringExp(loc, assumeUnique(s[0..len])); | |
61 es.sz = cast(ubyte)sz; | |
62 es.committed = 1; | |
63 e = es; | |
64 } | |
65 else | |
66 { | |
67 // Create an ArrayLiteralExp | |
68 Expressions elements = new Expressions(); | |
69 elements.push(cast(void*)e); | |
70 e = new ArrayLiteralExp(e.loc, elements); | |
71 } | |
72 e.type = type; | |
73 return e; | |
74 } | |
75 else if (e1.op == TOKstring && e2.op == TOKstring) | |
76 { | |
77 // Concatenate the strings | |
78 StringExp es1 = cast(StringExp)e1; | |
79 StringExp es2 = cast(StringExp)e2; | |
80 | |
81 size_t len = es1.len + es2.len; | |
82 int sz = es1.sz; | |
83 | |
84 if (sz != es2.sz) | |
85 { | |
86 /* Can happen with: | |
87 * auto s = "foo"d ~ "bar"c; | |
88 */ | |
89 assert(global.errors); | |
90 return e; | |
91 } | |
92 | |
93 char* s = cast(char*)malloc((len + 1) * sz); | |
94 memcpy(s, es1.string_, es1.len * sz); | |
95 memcpy(s + es1.len * sz, es2.string_, es2.len * sz); | |
96 | |
97 // Add terminating 0 | |
98 memset(s + len * sz, 0, sz); | |
99 | |
100 StringExp es = new StringExp(loc, assumeUnique(s[0..len])); | |
101 es.sz = cast(ubyte)sz; | |
102 es.committed = es1.committed | es2.committed; | |
103 | |
104 Type tt; | |
105 if (es1.committed) | |
106 tt = es1.type; | |
107 else | |
108 tt = es2.type; | |
109 | |
110 es.type = type; | |
111 e = es; | |
112 } | |
113 else if (e1.op == TOKstring && e2.op == TOKint64) | |
114 { | |
115 // Concatenate the strings | |
116 StringExp es1 = cast(StringExp)e1; | |
117 size_t len = es1.len + 1; | |
118 int sz = es1.sz; | |
119 ulong v = e2.toInteger(); | |
120 | |
121 char* s = cast(char*)malloc((len + 1) * sz); | |
122 memcpy(s, es1.string_, es1.len * sz); | |
123 memcpy(s + es1.len * sz, &v, sz); | |
124 | |
125 // Add terminating 0 | |
126 memset(s + len * sz, 0, sz); | |
127 | |
128 StringExp es = new StringExp(loc, assumeUnique(s[0..len])); | |
129 es.sz = cast(ubyte)sz; | |
130 es.committed = es1.committed; | |
131 Type tt = es1.type; | |
132 es.type = type; | |
133 e = es; | |
134 } | |
135 else if (e1.op == TOKint64 && e2.op == TOKstring) | |
136 { | |
137 // Concatenate the strings | |
138 StringExp es2 = cast(StringExp)e2; | |
139 size_t len = 1 + es2.len; | |
140 int sz = es2.sz; | |
141 ulong v = e1.toInteger(); | |
142 | |
143 char* s = cast(char*)malloc((len + 1) * sz); | |
144 memcpy(s, &v, sz); | |
145 memcpy(s + sz, es2.string_, es2.len * sz); | |
146 | |
147 // Add terminating 0 | |
148 memset(s + len * sz, 0, sz); | |
149 | |
150 StringExp es = new StringExp(loc, assumeUnique(s[0..len])); | |
151 es.sz = cast(ubyte)sz; | |
152 es.committed = es2.committed; | |
153 Type tt = es2.type; | |
154 es.type = type; | |
155 e = es; | |
156 } | |
157 else if (e1.op == TOKarrayliteral && e2.op == TOKarrayliteral && | |
158 t1.nextOf().equals(t2.nextOf())) | |
159 { | |
160 // Concatenate the arrays | |
161 ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1; | |
162 ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2; | |
163 | |
164 es1 = new ArrayLiteralExp(es1.loc, cast(Expressions)es1.elements.copy()); | |
165 es1.elements.insert(es1.elements.dim, es2.elements); | |
166 e = es1; | |
167 | |
168 if (type.toBasetype().ty == Tsarray) | |
169 { | |
170 e.type = new TypeSArray(t1.nextOf(), new IntegerExp(loc, es1.elements.dim, Type.tindex)); | |
171 e.type = e.type.semantic(loc, null); | |
172 } | |
173 else | |
174 e.type = type; | |
175 } | |
176 else if (e1.op == TOKarrayliteral && e2.op == TOKnull && | |
177 t1.nextOf().equals(t2.nextOf())) | |
178 { | |
179 e = e1; | |
180 goto L3; | |
181 } | |
182 else if (e1.op == TOKnull && e2.op == TOKarrayliteral && | |
183 t1.nextOf().equals(t2.nextOf())) | |
184 { | |
185 e = e2; | |
186 L3: | |
187 // Concatenate the array with null | |
188 ArrayLiteralExp es = cast(ArrayLiteralExp)e; | |
189 | |
190 es = new ArrayLiteralExp(es.loc, cast(Expressions)es.elements.copy()); | |
191 e = es; | |
192 | |
193 if (type.toBasetype().ty == Tsarray) | |
194 { | |
195 e.type = new TypeSArray(t1.nextOf(), new IntegerExp(loc, es.elements.dim, Type.tindex)); | |
196 e.type = e.type.semantic(loc, null); | |
197 } | |
198 else | |
199 e.type = type; | |
200 } | |
201 else if ((e1.op == TOKarrayliteral || e1.op == TOKnull) && | |
202 e1.type.toBasetype().nextOf().equals(e2.type)) | |
203 { | |
204 ArrayLiteralExp es1; | |
205 if (e1.op == TOKarrayliteral) | |
206 { es1 = cast(ArrayLiteralExp)e1; | |
207 es1 = new ArrayLiteralExp(es1.loc, cast(Expressions)es1.elements.copy()); | |
208 es1.elements.push(cast(void*)e2); | |
209 } | |
210 else | |
211 { | |
212 es1 = new ArrayLiteralExp(e1.loc, e2); | |
213 } | |
214 e = es1; | |
215 | |
216 if (type.toBasetype().ty == Tsarray) | |
217 { | |
218 e.type = new TypeSArray(e2.type, new IntegerExp(loc, es1.elements.dim, Type.tindex)); | |
219 e.type = e.type.semantic(loc, null); | |
220 } | |
221 else | |
222 e.type = type; | |
223 } | |
224 else if (e2.op == TOKarrayliteral && | |
225 e2.type.toBasetype().nextOf().equals(e1.type)) | |
226 { | |
227 ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2; | |
228 | |
229 es2 = new ArrayLiteralExp(es2.loc, cast(Expressions)es2.elements.copy()); | |
230 es2.elements.shift(cast(void*)e1); | |
231 e = es2; | |
232 | |
233 if (type.toBasetype().ty == Tsarray) | |
234 { | |
235 e.type = new TypeSArray(e1.type, new IntegerExp(loc, es2.elements.dim, Type.tindex)); | |
236 e.type = e.type.semantic(loc, null); | |
237 } | |
238 else | |
239 e.type = type; | |
240 } | |
241 else if (e1.op == TOKnull && e2.op == TOKstring) | |
242 { | |
243 t = e1.type; | |
244 e = e2; | |
245 goto L1; | |
246 } | |
247 else if (e1.op == TOKstring && e2.op == TOKnull) | |
248 { | |
249 e = e1; | |
250 t = e2.type; | |
251 L1: | |
252 Type tb = t.toBasetype(); | |
253 if (tb.ty == Tarray && tb.nextOf().equals(e.type)) | |
254 { | |
255 Expressions expressions = new Expressions(); | |
256 expressions.push(cast(void*)e); | |
257 e = new ArrayLiteralExp(loc, expressions); | |
258 e.type = t; | |
259 } | |
260 if (!e.type.equals(type)) | |
261 { | |
262 StringExp se = cast(StringExp)e.copy(); | |
263 e = se.castTo(null, type); | |
264 } | |
265 } | |
266 return e; | |
267 } |