comparison dmd/arrayop.c @ 510:6aee82889553

Merged DMD 1.034, array operations are not yet implemented ;)
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Thu, 14 Aug 2008 06:55:41 +0200
parents
children eef8ac26c66c
comparison
equal deleted inserted replaced
509:337554fd34f1 510:6aee82889553
1
2 // Copyright (c) 1999-2008 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <assert.h>
13
14 #if _WIN32 || IN_GCC || IN_LLVM
15 #include "mem.h"
16 #else
17 #include "../root/mem.h"
18 #endif
19
20 #include "stringtable.h"
21
22 #include "expression.h"
23 #include "statement.h"
24 #include "mtype.h"
25 #include "declaration.h"
26 #include "scope.h"
27 #include "id.h"
28 #include "module.h"
29 #include "init.h"
30
31 // FIXME
32 int binary(const char *p , const char **tab, int high)
33 {
34 assert(0);
35 }
36
37 /**************************************
38 * Hash table of array op functions already generated or known about.
39 */
40
41 StringTable arrayfuncs;
42
43 /***********************************
44 * Construct the array operation expression.
45 */
46
47 Expression *BinExp::arrayOp(Scope *sc)
48 {
49 // FIXME
50 error("array operations not yet implemented");
51 fatal();
52
53 Expressions *arguments = new Expressions();
54
55 /* The expression to generate an array operation for is mangled
56 * into a name to use as the array operation function name.
57 * Mangle in the operands and operators in RPN order, and type.
58 */
59 OutBuffer buf;
60 buf.writestring("_array");
61 buildArrayIdent(&buf, arguments);
62 buf.writeByte('_');
63
64 /* Append deco of array element type
65 */
66 #if DMDV2
67 buf.writestring(type->toBasetype()->nextOf()->toBasetype()->mutableOf()->deco);
68 #else
69 buf.writestring(type->toBasetype()->nextOf()->toBasetype()->deco);
70 #endif
71
72 size_t namelen = buf.offset;
73 buf.writeByte(0);
74 char *name = (char *)buf.extractData();
75
76 /* Look up name in hash table
77 */
78 StringValue *sv = arrayfuncs.update(name, namelen);
79 FuncDeclaration *fd = (FuncDeclaration *)sv->ptrvalue;
80 if (!fd)
81 {
82 /* Some of the array op functions are written as library functions,
83 * presumably to optimize them with special CPU vector instructions.
84 * List those library functions here, in alpha order.
85 */
86 static const char *libArrayopFuncs[] =
87 {
88 "_arrayExpSliceAddass_a",
89 "_arrayExpSliceAddass_d", // T[]+=T
90 "_arrayExpSliceAddass_f", // T[]+=T
91 "_arrayExpSliceAddass_g",
92 "_arrayExpSliceAddass_h",
93 "_arrayExpSliceAddass_i",
94 "_arrayExpSliceAddass_k",
95 "_arrayExpSliceAddass_s",
96 "_arrayExpSliceAddass_t",
97 "_arrayExpSliceAddass_u",
98 "_arrayExpSliceAddass_w",
99
100 "_arrayExpSliceDivass_d", // T[]/=T
101 "_arrayExpSliceDivass_f", // T[]/=T
102
103 "_arrayExpSliceMinSliceAssign_a",
104 "_arrayExpSliceMinSliceAssign_d", // T[]=T-T[]
105 "_arrayExpSliceMinSliceAssign_f", // T[]=T-T[]
106 "_arrayExpSliceMinSliceAssign_g",
107 "_arrayExpSliceMinSliceAssign_h",
108 "_arrayExpSliceMinSliceAssign_i",
109 "_arrayExpSliceMinSliceAssign_k",
110 "_arrayExpSliceMinSliceAssign_s",
111 "_arrayExpSliceMinSliceAssign_t",
112 "_arrayExpSliceMinSliceAssign_u",
113 "_arrayExpSliceMinSliceAssign_w",
114
115 "_arrayExpSliceMinass_a",
116 "_arrayExpSliceMinass_d", // T[]-=T
117 "_arrayExpSliceMinass_f", // T[]-=T
118 "_arrayExpSliceMinass_g",
119 "_arrayExpSliceMinass_h",
120 "_arrayExpSliceMinass_i",
121 "_arrayExpSliceMinass_k",
122 "_arrayExpSliceMinass_s",
123 "_arrayExpSliceMinass_t",
124 "_arrayExpSliceMinass_u",
125 "_arrayExpSliceMinass_w",
126
127 "_arrayExpSliceMulass_d", // T[]*=T
128 "_arrayExpSliceMulass_f", // T[]*=T
129 "_arrayExpSliceMulass_i",
130 "_arrayExpSliceMulass_k",
131 "_arrayExpSliceMulass_s",
132 "_arrayExpSliceMulass_t",
133 "_arrayExpSliceMulass_u",
134 "_arrayExpSliceMulass_w",
135
136 "_arraySliceExpAddSliceAssign_a",
137 "_arraySliceExpAddSliceAssign_d", // T[]=T[]+T
138 "_arraySliceExpAddSliceAssign_f", // T[]=T[]+T
139 "_arraySliceExpAddSliceAssign_g",
140 "_arraySliceExpAddSliceAssign_h",
141 "_arraySliceExpAddSliceAssign_i",
142 "_arraySliceExpAddSliceAssign_k",
143 "_arraySliceExpAddSliceAssign_s",
144 "_arraySliceExpAddSliceAssign_t",
145 "_arraySliceExpAddSliceAssign_u",
146 "_arraySliceExpAddSliceAssign_w",
147
148 "_arraySliceExpDivSliceAssign_d", // T[]=T[]/T
149 "_arraySliceExpDivSliceAssign_f", // T[]=T[]/T
150
151 "_arraySliceExpMinSliceAssign_a",
152 "_arraySliceExpMinSliceAssign_d", // T[]=T[]-T
153 "_arraySliceExpMinSliceAssign_f", // T[]=T[]-T
154 "_arraySliceExpMinSliceAssign_g",
155 "_arraySliceExpMinSliceAssign_h",
156 "_arraySliceExpMinSliceAssign_i",
157 "_arraySliceExpMinSliceAssign_k",
158 "_arraySliceExpMinSliceAssign_s",
159 "_arraySliceExpMinSliceAssign_t",
160 "_arraySliceExpMinSliceAssign_u",
161 "_arraySliceExpMinSliceAssign_w",
162
163 "_arraySliceExpMulSliceAddass_d", // T[] += T[]*T
164 "_arraySliceExpMulSliceAddass_f",
165 "_arraySliceExpMulSliceAddass_r",
166
167 "_arraySliceExpMulSliceAssign_d", // T[]=T[]*T
168 "_arraySliceExpMulSliceAssign_f", // T[]=T[]*T
169 "_arraySliceExpMulSliceAssign_i",
170 "_arraySliceExpMulSliceAssign_k",
171 "_arraySliceExpMulSliceAssign_s",
172 "_arraySliceExpMulSliceAssign_t",
173 "_arraySliceExpMulSliceAssign_u",
174 "_arraySliceExpMulSliceAssign_w",
175
176 "_arraySliceExpMulSliceMinass_d", // T[] -= T[]*T
177 "_arraySliceExpMulSliceMinass_f",
178 "_arraySliceExpMulSliceMinass_r",
179
180 "_arraySliceSliceAddSliceAssign_a",
181 "_arraySliceSliceAddSliceAssign_d", // T[]=T[]+T[]
182 "_arraySliceSliceAddSliceAssign_f", // T[]=T[]+T[]
183 "_arraySliceSliceAddSliceAssign_g",
184 "_arraySliceSliceAddSliceAssign_h",
185 "_arraySliceSliceAddSliceAssign_i",
186 "_arraySliceSliceAddSliceAssign_k",
187 "_arraySliceSliceAddSliceAssign_r", // T[]=T[]+T[]
188 "_arraySliceSliceAddSliceAssign_s",
189 "_arraySliceSliceAddSliceAssign_t",
190 "_arraySliceSliceAddSliceAssign_u",
191 "_arraySliceSliceAddSliceAssign_w",
192
193 "_arraySliceSliceAddass_a",
194 "_arraySliceSliceAddass_d", // T[]+=T[]
195 "_arraySliceSliceAddass_f", // T[]+=T[]
196 "_arraySliceSliceAddass_g",
197 "_arraySliceSliceAddass_h",
198 "_arraySliceSliceAddass_i",
199 "_arraySliceSliceAddass_k",
200 "_arraySliceSliceAddass_s",
201 "_arraySliceSliceAddass_t",
202 "_arraySliceSliceAddass_u",
203 "_arraySliceSliceAddass_w",
204
205 "_arraySliceSliceMinSliceAssign_a",
206 "_arraySliceSliceMinSliceAssign_d", // T[]=T[]-T[]
207 "_arraySliceSliceMinSliceAssign_f", // T[]=T[]-T[]
208 "_arraySliceSliceMinSliceAssign_g",
209 "_arraySliceSliceMinSliceAssign_h",
210 "_arraySliceSliceMinSliceAssign_i",
211 "_arraySliceSliceMinSliceAssign_k",
212 "_arraySliceSliceMinSliceAssign_r", // T[]=T[]-T[]
213 "_arraySliceSliceMinSliceAssign_s",
214 "_arraySliceSliceMinSliceAssign_t",
215 "_arraySliceSliceMinSliceAssign_u",
216 "_arraySliceSliceMinSliceAssign_w",
217
218 "_arraySliceSliceMinass_a",
219 "_arraySliceSliceMinass_d", // T[]-=T[]
220 "_arraySliceSliceMinass_f", // T[]-=T[]
221 "_arraySliceSliceMinass_g",
222 "_arraySliceSliceMinass_h",
223 "_arraySliceSliceMinass_i",
224 "_arraySliceSliceMinass_k",
225 "_arraySliceSliceMinass_s",
226 "_arraySliceSliceMinass_t",
227 "_arraySliceSliceMinass_u",
228 "_arraySliceSliceMinass_w",
229
230 "_arraySliceSliceMulSliceAssign_d", // T[]=T[]*T[]
231 "_arraySliceSliceMulSliceAssign_f", // T[]=T[]*T[]
232 "_arraySliceSliceMulSliceAssign_i",
233 "_arraySliceSliceMulSliceAssign_k",
234 "_arraySliceSliceMulSliceAssign_s",
235 "_arraySliceSliceMulSliceAssign_t",
236 "_arraySliceSliceMulSliceAssign_u",
237 "_arraySliceSliceMulSliceAssign_w",
238
239 "_arraySliceSliceMulass_d", // T[]*=T[]
240 "_arraySliceSliceMulass_f", // T[]*=T[]
241 "_arraySliceSliceMulass_i",
242 "_arraySliceSliceMulass_k",
243 "_arraySliceSliceMulass_s",
244 "_arraySliceSliceMulass_t",
245 "_arraySliceSliceMulass_u",
246 "_arraySliceSliceMulass_w",
247 };
248
249 int i = binary(name, libArrayopFuncs, sizeof(libArrayopFuncs) / sizeof(char *));
250 if (i == -1)
251 {
252 #ifdef DEBUG // Make sure our array is alphabetized
253 for (i = 0; i < sizeof(libArrayopFuncs) / sizeof(char *); i++)
254 {
255 if (strcmp(name, libArrayopFuncs[i]) == 0)
256 assert(0);
257 }
258 #endif
259 /* Not in library, so generate it.
260 * Construct the function body:
261 * foreach (i; 0 .. p.length) for (size_t i = 0; i < p.length; i++)
262 * loopbody;
263 * return p;
264 */
265
266 Arguments *fparams = new Arguments();
267 Expression *loopbody = buildArrayLoop(fparams);
268 Argument *p = (Argument *)fparams->data[0 /*fparams->dim - 1*/];
269 #if DMDV1
270 // for (size_t i = 0; i < p.length; i++)
271 Initializer *init = new ExpInitializer(0, new IntegerExp(0, 0, Type::tsize_t));
272 Dsymbol *d = new VarDeclaration(0, Type::tsize_t, Id::p, init);
273 Statement *s1 = new ForStatement(0,
274 new DeclarationStatement(0, d),
275 new CmpExp(TOKlt, 0, new IdentifierExp(0, Id::p), new ArrayLengthExp(0, new IdentifierExp(0, p->ident))),
276 new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id::p)),
277 new ExpStatement(0, loopbody));
278 #else
279 // foreach (i; 0 .. p.length)
280 Statement *s1 = new ForeachRangeStatement(0, TOKforeach,
281 new Argument(0, NULL, Id::p, NULL),
282 new IntegerExp(0, 0, Type::tint32),
283 new ArrayLengthExp(0, new IdentifierExp(0, p->ident)),
284 new ExpStatement(0, loopbody));
285 #endif
286 Statement *s2 = new ReturnStatement(0, new IdentifierExp(0, p->ident));
287 //printf("s2: %s\n", s2->toChars());
288 Statement *fbody = new CompoundStatement(0, s1, s2);
289
290 /* Construct the function
291 */
292 TypeFunction *ftype = new TypeFunction(fparams, type, 0, LINKc);
293 //printf("ftype: %s\n", ftype->toChars());
294 fd = new FuncDeclaration(0, 0, Lexer::idPool(name), STCundefined, ftype);
295 fd->fbody = fbody;
296 fd->protection = PROTpublic;
297 fd->linkage = LINKc;
298
299 sc->module->importedFrom->members->push(fd);
300
301 sc = sc->push();
302 sc->parent = sc->module->importedFrom;
303 sc->stc = 0;
304 sc->linkage = LINKc;
305 fd->semantic(sc);
306 sc->pop();
307 }
308 else
309 { /* In library, refer to it.
310 */
311 // LLVMDC FIXME
312 fd = FuncDeclaration::genCfunc(NULL, type, name);
313 }
314 sv->ptrvalue = fd; // cache symbol in hash table
315 }
316
317 /* Call the function fd(arguments)
318 */
319 Expression *ec = new VarExp(0, fd);
320 Expression *e = new CallExp(loc, ec, arguments);
321 e->type = type;
322 return e;
323 }
324
325 /******************************************
326 * Construct the identifier for the array operation function,
327 * and build the argument list to pass to it.
328 */
329
330 void Expression::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
331 {
332 buf->writestring("Exp");
333 arguments->shift(this);
334 }
335
336 void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
337 {
338 buf->writestring("Slice");
339 arguments->shift(this);
340 }
341
342 void AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
343 {
344 /* Evaluate assign expressions right to left
345 */
346 e2->buildArrayIdent(buf, arguments);
347 e1->buildArrayIdent(buf, arguments);
348 buf->writestring("Assign");
349 }
350
351 #define X(Str) \
352 void Str##AssignExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
353 { \
354 /* Evaluate assign expressions right to left \
355 */ \
356 e2->buildArrayIdent(buf, arguments); \
357 e1->buildArrayIdent(buf, arguments); \
358 buf->writestring(#Str); \
359 buf->writestring("ass"); \
360 }
361
362 X(Add)
363 X(Min)
364 X(Mul)
365 X(Div)
366 X(Mod)
367 X(Xor)
368 X(And)
369 X(Or)
370
371 #undef X
372
373 void NegExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
374 {
375 e1->buildArrayIdent(buf, arguments);
376 buf->writestring("Neg");
377 }
378
379 void ComExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
380 {
381 e1->buildArrayIdent(buf, arguments);
382 buf->writestring("Com");
383 }
384
385 #define X(Str) \
386 void Str##Exp::buildArrayIdent(OutBuffer *buf, Expressions *arguments) \
387 { \
388 /* Evaluate assign expressions left to right \
389 */ \
390 e1->buildArrayIdent(buf, arguments); \
391 e2->buildArrayIdent(buf, arguments); \
392 buf->writestring(#Str); \
393 }
394
395 X(Add)
396 X(Min)
397 X(Mul)
398 X(Div)
399 X(Mod)
400 X(Xor)
401 X(And)
402 X(Or)
403
404 #undef X
405
406 /******************************************
407 * Construct the inner loop for the array operation function,
408 * and build the parameter list.
409 */
410
411 Expression *Expression::buildArrayLoop(Arguments *fparams)
412 {
413 Identifier *id = Identifier::generateId("c", fparams->dim);
414 Argument *param = new Argument(0, type, id, NULL);
415 fparams->shift(param);
416 Expression *e = new IdentifierExp(0, id);
417 return e;
418 }
419
420 Expression *SliceExp::buildArrayLoop(Arguments *fparams)
421 {
422 Identifier *id = Identifier::generateId("p", fparams->dim);
423 Argument *param = new Argument(STCconst, type, id, NULL);
424 fparams->shift(param);
425 Expression *e = new IdentifierExp(0, id);
426 Expressions *arguments = new Expressions();
427 Expression *index = new IdentifierExp(0, Id::p);
428 arguments->push(index);
429 e = new ArrayExp(0, e, arguments);
430 return e;
431 }
432
433 Expression *AssignExp::buildArrayLoop(Arguments *fparams)
434 {
435 /* Evaluate assign expressions right to left
436 */
437 Expression *ex2 = e2->buildArrayLoop(fparams);
438 Expression *ex1 = e1->buildArrayLoop(fparams);
439 Argument *param = (Argument *)fparams->data[0];
440 param->storageClass = 0;
441 Expression *e = new AssignExp(0, ex1, ex2);
442 return e;
443 }
444
445 #define X(Str) \
446 Expression *Str##AssignExp::buildArrayLoop(Arguments *fparams) \
447 { \
448 /* Evaluate assign expressions right to left \
449 */ \
450 Expression *ex2 = e2->buildArrayLoop(fparams); \
451 Expression *ex1 = e1->buildArrayLoop(fparams); \
452 Argument *param = (Argument *)fparams->data[0]; \
453 param->storageClass = 0; \
454 Expression *e = new Str##AssignExp(0, ex1, ex2); \
455 return e; \
456 }
457
458 X(Add)
459 X(Min)
460 X(Mul)
461 X(Div)
462 X(Mod)
463 X(Xor)
464 X(And)
465 X(Or)
466
467 #undef X
468
469 Expression *NegExp::buildArrayLoop(Arguments *fparams)
470 {
471 Expression *ex1 = e1->buildArrayLoop(fparams);
472 Expression *e = new NegExp(0, ex1);
473 return e;
474 }
475
476 Expression *ComExp::buildArrayLoop(Arguments *fparams)
477 {
478 Expression *ex1 = e1->buildArrayLoop(fparams);
479 Expression *e = new ComExp(0, ex1);
480 return e;
481 }
482
483 #define X(Str) \
484 Expression *Str##Exp::buildArrayLoop(Arguments *fparams) \
485 { \
486 /* Evaluate assign expressions left to right \
487 */ \
488 Expression *ex1 = e1->buildArrayLoop(fparams); \
489 Expression *ex2 = e2->buildArrayLoop(fparams); \
490 Expression *e = new Str##Exp(0, ex1, ex2); \
491 return e; \
492 }
493
494 X(Add)
495 X(Min)
496 X(Mul)
497 X(Div)
498 X(Mod)
499 X(Xor)
500 X(And)
501 X(Or)
502
503 #undef X
504
505