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 }