Mercurial > projects > ddmd
comparison dmd/expression/Util.d @ 130:60bb0fe4563e
dmdfe 2.037 first main iteration
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Thu, 09 Sep 2010 22:51:44 +0100 |
parents | 010eb8f0e18d |
children | af1bebfd96a4 |
comparison
equal
deleted
inserted
replaced
129:010eb8f0e18d | 130:60bb0fe4563e |
---|---|
22 import dmd.STC; | 22 import dmd.STC; |
23 import dmd.WANT; | 23 import dmd.WANT; |
24 import dmd.IndexExp; | 24 import dmd.IndexExp; |
25 import dmd.AssignExp; | 25 import dmd.AssignExp; |
26 import dmd.CommaExp; | 26 import dmd.CommaExp; |
27 import dmd.Argument; | 27 import dmd.CondExp; |
28 import dmd.Parameter; | |
28 import dmd.DefaultInitExp; | 29 import dmd.DefaultInitExp; |
29 import dmd.Identifier; | 30 import dmd.Identifier; |
30 import dmd.Dsymbol; | 31 import dmd.Dsymbol; |
31 import dmd.Global; | 32 import dmd.Global; |
32 import dmd.ScopeDsymbol; | 33 import dmd.ScopeDsymbol; |
62 import dmd.PREC; | 63 import dmd.PREC; |
63 import dmd.Util; | 64 import dmd.Util; |
64 import dmd.TypeAArray; | 65 import dmd.TypeAArray; |
65 import dmd.Id; | 66 import dmd.Id; |
66 import dmd.PtrExp; | 67 import dmd.PtrExp; |
68 import dmd.ErrorExp; | |
67 | 69 |
68 import std.stdio : writef; | 70 import std.stdio : writef; |
69 | 71 |
70 import core.stdc.math; | 72 import core.stdc.math; |
71 import core.stdc.string; | 73 import core.stdc.string; |
186 */ | 188 */ |
187 | 189 |
188 struct Param2 | 190 struct Param2 |
189 { | 191 { |
190 Match* m; | 192 Match* m; |
193 version(DMDV2) { | |
191 Expression ethis; | 194 Expression ethis; |
195 int property; // 0: unintialized | |
196 // 1: seen @property | |
197 // 2: not @property | |
198 } | |
192 Expressions arguments; | 199 Expressions arguments; |
193 | 200 |
194 int fp2(void*, FuncDeclaration f) | 201 int fp2(void* param, FuncDeclaration f) |
195 { | 202 { |
203 auto p = cast(Param2*)param; | |
196 MATCH match; | 204 MATCH match; |
197 | 205 |
198 if (f != m.lastf) // skip duplicates | 206 if (f != m.lastf) // skip duplicates |
199 { | 207 { |
200 m.anyf = f; | 208 m.anyf = f; |
201 TypeFunction tf = cast(TypeFunction)f.type; | 209 TypeFunction tf = cast(TypeFunction)f.type; |
210 | |
211 int property = (tf.isproperty) ? 1 : 2; | |
212 if (p.property == 0) | |
213 p.property = property; | |
214 else if (p.property != property) | |
215 error(f.loc, "cannot overload both property and non-property functions"); | |
216 | |
202 match = tf.callMatch(f.needThis() ? ethis : null, arguments); | 217 match = tf.callMatch(f.needThis() ? ethis : null, arguments); |
203 //printf("test: match = %d\n", match); | 218 //printf("test: match = %d\n", match); |
204 if (match != MATCH.MATCHnomatch) | 219 if (match != MATCH.MATCHnomatch) |
205 { | 220 { |
206 if (match > m.last) | 221 if (match > m.last) |
214 if (m.lastf.overrides(f)) | 229 if (m.lastf.overrides(f)) |
215 goto LlastIsBetter; | 230 goto LlastIsBetter; |
216 else if (f.overrides(m.lastf)) | 231 else if (f.overrides(m.lastf)) |
217 goto LfIsBetter; | 232 goto LfIsBetter; |
218 | 233 |
234 version(DMDV2) { | |
219 /* Try to disambiguate using template-style partial ordering rules. | 235 /* Try to disambiguate using template-style partial ordering rules. |
220 * In essence, if f() and g() are ambiguous, if f() can call g(), | 236 * In essence, if f() and g() are ambiguous, if f() can call g(), |
221 * but g() cannot call f(), then pick f(). | 237 * but g() cannot call f(), then pick f(). |
222 * This is because f() is "more specialized." | 238 * This is because f() is "more specialized." |
223 */ | 239 */ |
228 if (c1 > c2) | 244 if (c1 > c2) |
229 goto LfIsBetter; | 245 goto LfIsBetter; |
230 if (c1 < c2) | 246 if (c1 < c2) |
231 goto LlastIsBetter; | 247 goto LlastIsBetter; |
232 } | 248 } |
249 } | |
233 | 250 |
234 Lambiguous: | 251 Lambiguous: |
235 m.nextf = f; | 252 m.nextf = f; |
236 m.count++; | 253 m.count++; |
237 return 0; | 254 return 0; |
262 this.f = f; | 279 this.f = f; |
263 return 1; | 280 return 1; |
264 } | 281 } |
265 | 282 |
266 version (DMDV2) { | 283 version (DMDV2) { |
267 /* Allow covariant matches, if it's just a const conversion | 284 /* Allow covariant matches, as long as the return type |
268 * of the return type | 285 * is just a const conversion. |
269 */ | 286 * This allows things like pure functions to match with an impure function type. |
287 */ | |
270 if (t.ty == Tfunction) | 288 if (t.ty == Tfunction) |
271 { | 289 { |
272 TypeFunction tf = cast(TypeFunction)f.type; | 290 TypeFunction tf = cast(TypeFunction)f.type; |
273 if (tf.covariant(t) == 1 && | 291 if (tf.covariant(t) == 1 && |
274 tf.nextOf().implicitConvTo(t.nextOf()) >= MATCHconst) | 292 tf.nextOf().implicitConvTo(t.nextOf()) >= MATCHconst) |
285 void overloadResolveX(Match* m, FuncDeclaration fstart, Expression ethis, Expressions arguments) | 303 void overloadResolveX(Match* m, FuncDeclaration fstart, Expression ethis, Expressions arguments) |
286 { | 304 { |
287 Param2 p; | 305 Param2 p; |
288 p.m = m; | 306 p.m = m; |
289 p.ethis = ethis; | 307 p.ethis = ethis; |
308 p.property = 0; | |
290 p.arguments = arguments; | 309 p.arguments = arguments; |
291 overloadApply(fstart, &p.fp2, &p); | 310 overloadApply(fstart, &p.fp2, &p); |
292 } | 311 } |
293 | 312 |
294 void templateResolve(Match* m, TemplateDeclaration td, Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions arguments) | 313 void templateResolve(Match* m, TemplateDeclaration td, Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions arguments) |
326 e = e.semantic(sc); | 345 e = e.semantic(sc); |
327 } | 346 } |
328 } | 347 } |
329 } | 348 } |
330 | 349 |
350 Expressions arrayExpressionToCommonType(Scope sc, Expressions exps, Type *pt) | |
351 { | |
352 //version(DMDV1) { | |
353 // /* The first element sets the type | |
354 // */ | |
355 // Type *t0 = NULL; | |
356 // for (size_t i = 0; i < exps->dim; i++) | |
357 // { Expression *e = (Expression *)exps->data[i]; | |
358 // | |
359 // if (!e->type) | |
360 // { error("%s has no value", e->toChars()); | |
361 // e = new ErrorExp(); | |
362 // } | |
363 // e = resolveProperties(sc, e); | |
364 // | |
365 // if (!t0) | |
366 // t0 = e->type; | |
367 // else | |
368 // e = e->implicitCastTo(sc, t0); | |
369 // exps->data[i] = (void *)e; | |
370 // } | |
371 // | |
372 // if (!t0) | |
373 // t0 = Type::tvoid; | |
374 // if (pt) | |
375 // *pt = t0; | |
376 // | |
377 // // Eventually, we want to make this copy-on-write | |
378 // return exps; | |
379 //} | |
380 version(DMDV2) { | |
381 /* The type is determined by applying ?: to each pair. | |
382 */ | |
383 /* Still have a problem with: | |
384 * ubyte[][] = [ cast(ubyte[])"hello", [1]]; | |
385 * which works if the array literal is initialized top down with the ubyte[][] | |
386 * type, but fails with this function doing bottom up typing. | |
387 */ | |
388 //printf("arrayExpressionToCommonType()\n"); | |
389 scope integerexp = new IntegerExp(0); | |
390 scope condexp = new CondExp(Loc(0), integerexp, null, null); | |
391 | |
392 Type t0; | |
393 Expression e0; | |
394 int j0; | |
395 foreach (size_t i, Expression e; exps) | |
396 { | |
397 e = resolveProperties(sc, e); | |
398 if (!e.type) | |
399 { error("%s has no value", e.toChars()); | |
400 e = new ErrorExp(); | |
401 } | |
402 | |
403 if (t0) | |
404 { | |
405 if (t0 != e.type) | |
406 { | |
407 /* This applies ?: to merge the types. It's backwards; | |
408 * ?: should call this function to merge types. | |
409 */ | |
410 condexp.type = null; | |
411 condexp.e1 = e0; | |
412 condexp.e2 = e; | |
413 condexp.semantic(sc); | |
414 exps[j0] = condexp.e1; | |
415 e = condexp.e2; | |
416 j0 = i; | |
417 e0 = e; | |
418 t0 = e0.type; | |
419 } | |
420 } | |
421 else | |
422 { | |
423 j0 = i; | |
424 e0 = e; | |
425 t0 = e.type; | |
426 } | |
427 exps[i] = e; | |
428 } | |
429 | |
430 if (t0) | |
431 { | |
432 foreach (ref Expression e; exps) | |
433 { | |
434 e = e.implicitCastTo(sc, t0); | |
435 } | |
436 } | |
437 else | |
438 t0 = Type.tvoid; // [] is typed as void[] | |
439 if (pt) | |
440 *pt = t0; | |
441 | |
442 // Eventually, we want to make this copy-on-write | |
443 return exps; | |
444 } | |
445 } | |
446 | |
331 /**************************************** | 447 /**************************************** |
332 * Preprocess arguments to function. | 448 * Preprocess arguments to function. |
333 */ | 449 */ |
334 | 450 |
335 void preFunctionArguments(Loc loc, Scope sc, Expressions exps) | 451 void preFunctionParameters(Loc loc, Scope sc, Expressions exps) |
336 { | 452 { |
337 if (exps) | 453 if (exps) |
338 { | 454 { |
339 expandTuples(exps); | 455 expandTuples(exps); |
340 | 456 |
478 * 3. do default promotions on arguments corresponding to ... | 594 * 3. do default promotions on arguments corresponding to ... |
479 * 4. add hidden _arguments[] argument | 595 * 4. add hidden _arguments[] argument |
480 * 5. call copy constructor for struct value arguments | 596 * 5. call copy constructor for struct value arguments |
481 */ | 597 */ |
482 | 598 |
483 void functionArguments(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) | 599 void functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) |
484 { | 600 { |
485 uint n; | 601 uint n; |
486 | 602 |
487 //printf("functionArguments()\n"); | 603 //printf("functionParameters()\n"); |
488 assert(arguments); | 604 assert(arguments); |
489 size_t nargs = arguments ? arguments.dim : 0; | 605 size_t nargs = arguments ? arguments.dim : 0; |
490 size_t nparams = Argument.dim(tf.parameters); | 606 size_t nparams = Parameter.dim(tf.parameters); |
491 | 607 |
492 if (nargs > nparams && tf.varargs == 0) | 608 if (nargs > nparams && tf.varargs == 0) |
493 error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars()); | 609 error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars()); |
494 | 610 |
495 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) | 611 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) |
506 | 622 |
507 Type tb; | 623 Type tb; |
508 | 624 |
509 if (i < nparams) | 625 if (i < nparams) |
510 { | 626 { |
511 auto p = Argument.getNth(tf.parameters, i); | 627 auto p = Parameter.getNth(tf.parameters, i); |
512 | 628 |
513 if (!arg) | 629 if (!arg) |
514 { | 630 { |
515 if (!p.defaultArg) | 631 if (!p.defaultArg) |
516 { | 632 { |
517 if (tf.varargs == 2 && i + 1 == nparams) | 633 if (tf.varargs == 2 && i + 1 == nparams) |
518 goto L2; | 634 goto L2; |
519 | 635 |
520 error(loc, "expected %d function arguments, not %d", nparams, nargs); | 636 error(loc, "expected %d function arguments, not %d", nparams, nargs); |
521 break; | 637 return; |
522 } | 638 } |
523 arg = p.defaultArg; | 639 arg = p.defaultArg; |
524 version (DMDV2) { | |
525 if (arg.op == TOK.TOKdefault) | |
526 { | |
527 DefaultInitExp de = cast(DefaultInitExp)arg; | |
528 arg = de.resolve(loc, sc); | |
529 } | |
530 else | |
531 { | |
532 arg = arg.copy(); | |
533 } | |
534 } else { | |
535 arg = arg.copy(); | 640 arg = arg.copy(); |
641 version (DMDV2) | |
642 { | |
643 arg = arg.resolveLoc(loc, sc); // __FILE__ and __LINE__ | |
536 } | 644 } |
537 arguments.push(arg); | 645 arguments.push(arg); |
538 nargs++; | 646 nargs++; |
539 } | 647 } |
540 | 648 |
542 { | 650 { |
543 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars()); | 651 //printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars()); |
544 if (arg.implicitConvTo(p.type)) | 652 if (arg.implicitConvTo(p.type)) |
545 { | 653 { |
546 if (nargs != nparams) | 654 if (nargs != nparams) |
655 { | |
547 error(loc, "expected %zu function arguments, not %zu", nparams, nargs); | 656 error(loc, "expected %zu function arguments, not %zu", nparams, nargs); |
657 return; | |
658 } | |
548 goto L1; | 659 goto L1; |
549 } | 660 } |
550 L2: | 661 L2: |
551 tb = p.type.toBasetype(); /// | 662 tb = p.type.toBasetype(); /// |
552 Type tret = p.isLazyArray(); | 663 Type tret = p.isLazyArray(); |
776 } | 887 } |
777 | 888 |
778 // If D linkage and variadic, add _arguments[] as first argument | 889 // If D linkage and variadic, add _arguments[] as first argument |
779 if (tf.linkage == LINK.LINKd && tf.varargs == 1) | 890 if (tf.linkage == LINK.LINKd && tf.varargs == 1) |
780 { | 891 { |
892 assert(arguments.dim >= nparams); | |
781 auto e = createTypeInfoArray(sc, &arguments[nparams], arguments.dim - nparams); | 893 auto e = createTypeInfoArray(sc, &arguments[nparams], arguments.dim - nparams); |
782 arguments.insert(0, e); | 894 arguments.insert(0, e); |
783 } | 895 } |
784 } | 896 } |
785 | 897 |
952 * point at its elements[]. | 1064 * point at its elements[]. |
953 */ | 1065 */ |
954 | 1066 |
955 /* Create the TypeTuple corresponding to the types of args[] | 1067 /* Create the TypeTuple corresponding to the types of args[] |
956 */ | 1068 */ |
957 Arguments args = new Arguments; | 1069 auto args = new Parameters; |
958 args.setDim(dim); | 1070 args.setDim(dim); |
959 for (size_t i = 0; i < dim; i++) | 1071 for (size_t i = 0; i < dim; i++) |
960 { | 1072 { |
961 Argument arg = new Argument(STCin, exps[i].type, null, null); | 1073 auto arg = new Parameter(STCin, exps[i].type, null, null); |
962 args[i] = arg; | 1074 args[i] = arg; |
963 } | 1075 } |
964 TypeTuple tup = new TypeTuple(args); | 1076 TypeTuple tup = new TypeTuple(args); |
965 Expression e = tup.getTypeInfo(sc); | 1077 Expression e = tup.getTypeInfo(sc); |
966 e = e.optimize(WANTvalue); | 1078 e = e.optimize(WANTvalue); |
1272 * Given array of arguments and an aggregate type, | 1384 * Given array of arguments and an aggregate type, |
1273 * if any of the argument types are missing, attempt to infer | 1385 * if any of the argument types are missing, attempt to infer |
1274 * them from the aggregate type. | 1386 * them from the aggregate type. |
1275 */ | 1387 */ |
1276 | 1388 |
1277 void inferApplyArgTypes(TOK op, Arguments arguments, Expression aggr) | 1389 void inferApplyArgTypes(TOK op, Parameters arguments, Expression aggr) |
1278 { | 1390 { |
1279 if (!arguments || !arguments.dim) | 1391 if (!arguments || !arguments.dim) |
1280 return; | 1392 return; |
1281 | 1393 |
1282 /* Return if no arguments need types. | 1394 /* Return if no arguments need types. |
1284 for (size_t u = 0; 1; u++) | 1396 for (size_t u = 0; 1; u++) |
1285 { | 1397 { |
1286 if (u == arguments.dim) | 1398 if (u == arguments.dim) |
1287 return; | 1399 return; |
1288 | 1400 |
1289 Argument arg = arguments[u]; | 1401 auto arg = arguments[u]; |
1290 if (!arg.type) | 1402 if (!arg.type) |
1291 break; | 1403 break; |
1292 } | 1404 } |
1293 | 1405 |
1294 AggregateDeclaration ad; | 1406 AggregateDeclaration ad; |
1295 | 1407 |
1296 Argument arg = arguments[0]; | 1408 auto arg = arguments[0]; |
1297 Type taggr = aggr.type; | 1409 Type taggr = aggr.type; |
1298 if (!taggr) | 1410 if (!taggr) |
1299 return; | 1411 return; |
1300 Type tab = taggr.toBasetype(); | 1412 Type tab = taggr.toBasetype(); |
1301 switch (tab.ty) | 1413 switch (tab.ty) |
1313 arg.type = tab.nextOf(); // value type | 1425 arg.type = tab.nextOf(); // value type |
1314 break; | 1426 break; |
1315 | 1427 |
1316 case TY.Taarray: | 1428 case TY.Taarray: |
1317 { | 1429 { |
1318 TypeAArray taa = cast(TypeAArray)tab; | 1430 auto taa = cast(TypeAArray)tab; |
1319 | 1431 |
1320 if (arguments.dim == 2) | 1432 if (arguments.dim == 2) |
1321 { | 1433 { |
1322 if (!arg.type) | 1434 if (!arg.type) |
1323 arg.type = taa.index; // key type | 1435 arg.type = taa.index; // key type |
1412 * analogous to func.overloadResolveX(). | 1524 * analogous to func.overloadResolveX(). |
1413 */ | 1525 */ |
1414 | 1526 |
1415 int fp3(void*, FuncDeclaration f) | 1527 int fp3(void*, FuncDeclaration f) |
1416 { | 1528 { |
1417 TypeFunction tf = cast(TypeFunction)f.type; | 1529 auto tf = cast(TypeFunction)f.type; |
1418 if (inferApplyArgTypesY(tf, arguments) == 1) | 1530 if (inferApplyArgTypesY(tf, arguments) == 1) |
1419 return 0; | 1531 return 0; |
1420 | 1532 |
1421 if (arguments.dim == 0) | 1533 if (arguments.dim == 0) |
1422 return 1; | 1534 return 1; |
1423 | 1535 |
1424 return 0; | 1536 return 0; |
1425 } | 1537 } |
1426 | 1538 |
1427 Arguments arguments; | 1539 Parameters arguments; |
1428 } | 1540 } |
1429 | 1541 |
1430 void inferApplyArgTypesX(FuncDeclaration fstart, Arguments arguments) | 1542 void inferApplyArgTypesX(FuncDeclaration fstart, Parameters arguments) |
1431 { | 1543 { |
1432 Param3 p3; | 1544 Param3 p3; |
1433 p3.arguments = arguments; | 1545 p3.arguments = arguments; |
1434 overloadApply(fstart, &p3.fp3, cast(void*)arguments); | 1546 overloadApply(fstart, &p3.fp3, cast(void*)arguments); |
1435 } | 1547 } |
1439 * Returns: | 1551 * Returns: |
1440 * 0 match for this function | 1552 * 0 match for this function |
1441 * 1 no match for this function | 1553 * 1 no match for this function |
1442 */ | 1554 */ |
1443 | 1555 |
1444 int inferApplyArgTypesY(TypeFunction tf, Arguments arguments) | 1556 int inferApplyArgTypesY(TypeFunction tf, Parameters arguments) |
1445 { | 1557 { |
1446 size_t nparams; | 1558 size_t nparams; |
1447 Argument p; | 1559 Parameter p; |
1448 | 1560 |
1449 if (Argument.dim(tf.parameters) != 1) | 1561 if (Parameter.dim(tf.parameters) != 1) |
1450 goto Lnomatch; | 1562 goto Lnomatch; |
1451 | 1563 |
1452 p = Argument.getNth(tf.parameters, 0); | 1564 p = Parameter.getNth(tf.parameters, 0); |
1453 if (p.type.ty != TY.Tdelegate) | 1565 if (p.type.ty != TY.Tdelegate) |
1454 goto Lnomatch; | 1566 goto Lnomatch; |
1455 | 1567 |
1456 tf = cast(TypeFunction)p.type.nextOf(); | 1568 tf = cast(TypeFunction)p.type.nextOf(); |
1457 assert(tf.ty == TY.Tfunction); | 1569 assert(tf.ty == TY.Tfunction); |
1458 | 1570 |
1459 /* We now have tf, the type of the delegate. Match it against | 1571 /* We now have tf, the type of the delegate. Match it against |
1460 * the arguments, filling in missing argument types. | 1572 * the arguments, filling in missing argument types. |
1461 */ | 1573 */ |
1462 nparams = Argument.dim(tf.parameters); | 1574 nparams = Parameter.dim(tf.parameters); |
1463 if (nparams == 0 || tf.varargs) | 1575 if (nparams == 0 || tf.varargs) |
1464 goto Lnomatch; // not enough parameters | 1576 goto Lnomatch; // not enough parameters |
1465 if (arguments.dim != nparams) | 1577 if (arguments.dim != nparams) |
1466 goto Lnomatch; // not enough parameters | 1578 goto Lnomatch; // not enough parameters |
1467 | 1579 |
1468 for (size_t u = 0; u < nparams; u++) | 1580 for (size_t u = 0; u < nparams; u++) |
1469 { | 1581 { |
1470 Argument arg = arguments[u]; | 1582 auto arg = arguments[u]; |
1471 Argument param = Argument.getNth(tf.parameters, u); | 1583 auto param = Parameter.getNth(tf.parameters, u); |
1472 if (arg.type) | 1584 if (arg.type) |
1473 { | 1585 { |
1474 if (!arg.type.equals(param.type)) | 1586 if (!arg.type.equals(param.type)) |
1475 { | 1587 { |
1476 /* Cannot resolve argument types. Indicate an | 1588 /* Cannot resolve argument types. Indicate an |