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