1 module d.semantic.expression;
2 
3 import d.semantic.caster;
4 import d.semantic.semantic;
5 
6 import d.ast.expression;
7 import d.ast.type;
8 
9 import d.ir.error;
10 import d.ir.expression;
11 import d.ir.symbol;
12 import d.ir.type;
13 
14 import source.location;
15 
16 import source.exception;
17 
18 alias TernaryExpression = d.ir.expression.TernaryExpression;
19 alias ArrayLiteral = d.ir.expression.ArrayLiteral;
20 alias CallExpression = d.ir.expression.CallExpression;
21 alias NewExpression = d.ir.expression.NewExpression;
22 
23 struct ExpressionVisitor {
24 	private SemanticPass pass;
25 	alias pass this;
26 
27 	this(SemanticPass pass) {
28 		this.pass = pass;
29 	}
30 
31 	Expression visit(AstExpression e) {
32 		return this.dispatch!((e) {
33 			throw new CompileException(
34 				e.location, typeid(e).toString() ~ " is not supported");
35 		})(e);
36 	}
37 
38 	Expression visit(ParenExpression e) {
39 		return visit(e.expr);
40 	}
41 
42 	Expression visit(BooleanLiteral e) {
43 		return e;
44 	}
45 
46 	Expression visit(IntegerLiteral e) {
47 		return e;
48 	}
49 
50 	Expression visit(FloatLiteral e) {
51 		return e;
52 	}
53 
54 	Expression visit(CharacterLiteral e) {
55 		return e;
56 	}
57 
58 	Expression visit(NullLiteral e) {
59 		return e;
60 	}
61 
62 	Expression visit(StringLiteral e) {
63 		return e;
64 	}
65 
66 private:
67 	ErrorExpression getError(Expression base, Location location, string msg) {
68 		return .getError(base, location, msg).expression;
69 	}
70 
71 	ErrorExpression getError(Expression base, string msg) {
72 		return getError(base, base.location, msg);
73 	}
74 
75 	ErrorExpression getError(Symbol base, Location location, string msg) {
76 		return .getError(base, location, msg).expression;
77 	}
78 
79 	ErrorExpression getError(Type t, Location location, string msg) {
80 		return .getError(t, location, msg).expression;
81 	}
82 
83 	Expression getTemporary(Expression value) {
84 		if (auto e = cast(ErrorExpression) value) {
85 			return e;
86 		}
87 
88 		auto loc = value.location;
89 
90 		import source.name;
91 		auto v = new Variable(loc, value.type, BuiltinName!"", value);
92 		v.step = Step.Processed;
93 
94 		return new VariableExpression(loc, v);
95 	}
96 
97 	Expression getLvalue(Expression value) {
98 		if (auto e = cast(ErrorExpression) value) {
99 			return e;
100 		}
101 
102 		import source.name;
103 		auto v = new Variable(value.location,
104 		                      value.type.getParamType(ParamKind.Ref),
105 		                      BuiltinName!"", value);
106 
107 		v.step = Step.Processed;
108 		return new VariableExpression(value.location, v);
109 	}
110 
111 	auto buildAssign(Location location, Expression lhs, Expression rhs) {
112 		if (!lhs.isLvalue) {
113 			return getError(lhs, "Expected an lvalue");
114 		}
115 
116 		auto type = lhs.type;
117 		rhs = buildImplicitCast(pass, rhs.location, type, rhs);
118 		return
119 			build!BinaryExpression(location, type, BinaryOp.Assign, lhs, rhs);
120 	}
121 
122 	Expression buildBinary(Location location, AstBinaryOp op, Expression lhs,
123 	                       Expression rhs) {
124 		if (op.isAssign()) {
125 			lhs = getLvalue(lhs);
126 			rhs = getTemporary(rhs);
127 
128 			auto type = lhs.type;
129 			auto llhs = build!BinaryExpression(location, type, BinaryOp.Comma,
130 			                                   rhs, lhs);
131 
132 			return buildAssign(location, lhs, buildExplicitCast(
133 				pass, location, type,
134 				buildBinary(location, op.getBaseOp(), llhs, rhs)));
135 		}
136 
137 		Type type;
138 		BinaryOp bop;
139 		ICmpOp icmpop;
140 		final switch (op) with (AstBinaryOp) {
141 			case Comma:
142 				return build!BinaryExpression(location, rhs.type,
143 				                              BinaryOp.Comma, lhs, rhs);
144 
145 			case Assign:
146 				return buildAssign(location, lhs, rhs);
147 
148 			case Add, Sub:
149 				auto c = lhs.type.getCanonical();
150 				if (c.kind == TypeKind.Pointer) {
151 					// FIXME: check that rhs is an integer.
152 					if (op == Sub) {
153 						rhs = build!UnaryExpression(rhs.location, rhs.type,
154 						                            UnaryOp.Minus, rhs);
155 					}
156 
157 					auto i =
158 						build!IndexExpression(location, c.element, lhs, rhs);
159 					return build!UnaryExpression(location, lhs.type,
160 					                             UnaryOp.AddressOf, i);
161 				}
162 
163 				goto case;
164 
165 			case Mul, Pow:
166 				bop = cast(BinaryOp) op;
167 				goto PromotedBinaryOp;
168 
169 			case Div, Rem:
170 				import d.semantic.typepromotion;
171 				type = getPromotedType(pass, location, lhs.type, rhs.type);
172 
173 				auto bt = type.builtin;
174 				auto signed = isIntegral(bt) && isSigned(bt);
175 
176 				// FIXME: We need some wrapper asserting + unitest for these.
177 				bop =
178 					cast(BinaryOp) (((op - Div) * 2) + BinaryOp.UDiv + signed);
179 				goto CastBinaryOp;
180 
181 			case Or, And, Xor:
182 			case LeftShift, UnsignedRightShift:
183 				// FIXME: We need some wrapper asserting + unitest for these.
184 				bop = cast(BinaryOp) (op - Or + BinaryOp.Or);
185 				goto PromotedBinaryOp;
186 
187 			PromotedBinaryOp:
188 				import d.semantic.typepromotion;
189 				type = getPromotedType(pass, location, lhs.type, rhs.type);
190 
191 				goto CastBinaryOp;
192 
193 			case SignedRightShift:
194 				import d.semantic.typepromotion;
195 				type = getPromotedType(pass, location, lhs.type, rhs.type);
196 
197 				auto bt = type.builtin;
198 				bop = (isIntegral(bt) && isSigned(bt))
199 					? BinaryOp.SignedRightShift
200 					: BinaryOp.UnsignedRightShift;
201 
202 				goto CastBinaryOp;
203 
204 			case LogicalOr, LogicalAnd:
205 				type = Type.get(BuiltinType.Bool);
206 
207 				// FIXME: We need some wrapper asserting + unitest for these.
208 				bop = cast(BinaryOp) (op - LogicalOr + BinaryOp.LogicalOr);
209 
210 				lhs = buildExplicitCast(pass, lhs.location, type, lhs);
211 				rhs = buildExplicitCast(pass, rhs.location, type, rhs);
212 
213 				goto BuildBinaryOp;
214 
215 			CastBinaryOp:
216 				lhs = buildImplicitCast(pass, lhs.location, type, lhs);
217 				rhs = buildImplicitCast(pass, rhs.location, type, rhs);
218 
219 				goto BuildBinaryOp;
220 
221 			BuildBinaryOp:
222 				return build!BinaryExpression(location, type, bop, lhs, rhs);
223 
224 			case Concat:
225 				type = lhs.type;
226 				if (type.getCanonical().kind != TypeKind.Slice) {
227 					return getError(lhs, "Expected a slice");
228 				}
229 
230 				rhs = buildImplicitCast(
231 					pass, rhs.location,
232 					(rhs.type.getCanonical().kind == TypeKind.Slice)
233 						? type
234 						: type.element,
235 					rhs);
236 
237 				return callOverloadSet(location, pass.object.getArrayConcat(),
238 				                       [lhs, rhs]);
239 
240 			case AddAssign, SubAssign:
241 			case MulAssign, PowAssign:
242 			case DivAssign, RemAssign:
243 			case OrAssign, AndAssign, XorAssign:
244 			case LeftShiftAssign:
245 			case UnsignedRightShiftAssign:
246 			case SignedRightShiftAssign:
247 			case LogicalOrAssign:
248 			case LogicalAndAssign:
249 			case ConcatAssign:
250 				assert(0, "Assign op should not reach this point");
251 
252 			case Equal, Identical:
253 				icmpop = ICmpOp.Equal;
254 				goto HandleICmp;
255 
256 			case NotEqual, NotIdentical:
257 				icmpop = ICmpOp.NotEqual;
258 				goto HandleICmp;
259 
260 			case Greater:
261 				icmpop = ICmpOp.Greater;
262 				goto HandleICmp;
263 
264 			case GreaterEqual:
265 				icmpop = ICmpOp.GreaterEqual;
266 				goto HandleICmp;
267 
268 			case Less:
269 				icmpop = ICmpOp.Less;
270 				goto HandleICmp;
271 
272 			case LessEqual:
273 				icmpop = ICmpOp.LessEqual;
274 				goto HandleICmp;
275 
276 			HandleICmp:
277 				import d.semantic.typepromotion;
278 				type = getPromotedType(pass, location, lhs.type, rhs.type);
279 
280 				lhs = buildImplicitCast(pass, lhs.location, type, lhs);
281 				rhs = buildImplicitCast(pass, rhs.location, type, rhs);
282 
283 				return build!ICmpExpression(location, icmpop, lhs, rhs);
284 
285 			case In:
286 			case NotIn:
287 				assert(0, "in and !in are not implemented.");
288 
289 			case LessGreater:
290 			case LessEqualGreater:
291 			case UnorderedLess:
292 			case UnorderedLessEqual:
293 			case UnorderedGreater:
294 			case UnorderedGreaterEqual:
295 			case Unordered:
296 			case UnorderedEqual:
297 				assert(0, "Unorderd comparisons are not implemented.");
298 		}
299 	}
300 
301 public:
302 	Expression visit(AstBinaryExpression e) {
303 		return buildBinary(e.location, e.op, visit(e.lhs), visit(e.rhs));
304 	}
305 
306 	Expression visit(AstTernaryExpression e) {
307 		auto condition = buildExplicitCast(pass, e.condition.location,
308 		                                   Type.get(BuiltinType.Bool),
309 		                                   visit(e.condition));
310 
311 		auto lhs = visit(e.lhs);
312 		auto rhs = visit(e.rhs);
313 
314 		import d.semantic.typepromotion;
315 		auto t = getPromotedType(pass, e.location, lhs.type, rhs.type);
316 
317 		lhs = buildExplicitCast(pass, lhs.location, t, lhs);
318 		rhs = buildExplicitCast(pass, rhs.location, t, rhs);
319 
320 		return build!TernaryExpression(e.location, t, condition, lhs, rhs);
321 	}
322 
323 	private Expression handleAddressOf(Expression expr) {
324 		// For fucked up reasons, &funcname is a special case.
325 		if (auto se = cast(FunctionExpression) expr) {
326 			return expr;
327 		} else if (auto pe = cast(PolysemousExpression) expr) {
328 			import std.algorithm, std.array;
329 			pe.expressions =
330 				pe.expressions.map!(e => handleAddressOf(e)).array();
331 			return pe;
332 		}
333 
334 		return build!UnaryExpression(expr.location, expr.type.getPointer(),
335 		                             UnaryOp.AddressOf, expr);
336 	}
337 
338 	Expression visit(AstUnaryExpression e) {
339 		auto expr = visit(e.expr);
340 		auto op = e.op;
341 
342 		Type type;
343 		final switch (op) with (UnaryOp) {
344 			case AddressOf:
345 				return handleAddressOf(expr);
346 
347 				// It could have been so simple :(
348 				/+
349 				type = expr.type.getPointer();
350 				break;
351 				+/
352 
353 			case Dereference:
354 				auto c = expr.type.getCanonical();
355 				if (c.kind == TypeKind.Pointer) {
356 					type = c.element;
357 					break;
358 				}
359 
360 				return getError(expr, e.location,
361 				                "Only pointers can be dereferenced");
362 
363 			case PreInc, PreDec:
364 			case PostInc, PostDec:
365 				// FIXME: check that type is integer or pointer.
366 				type = expr.type;
367 				break;
368 
369 			case Plus:
370 			case Minus:
371 			case Complement:
372 				// FIXME: check that type is integer.
373 				type = expr.type;
374 				break;
375 
376 			case Not:
377 				type = Type.get(BuiltinType.Bool);
378 				expr = buildExplicitCast(pass, expr.location, type, expr);
379 				break;
380 		}
381 
382 		return build!UnaryExpression(e.location, type, op, expr);
383 	}
384 
385 	Expression visit(AstCastExpression e) {
386 		import d.semantic.type;
387 		return buildExplicitCast(
388 			pass, e.location, TypeVisitor(pass).visit(e.type), visit(e.expr));
389 	}
390 
391 	Expression visit(AstArrayLiteral e) {
392 		import std.algorithm, std.array;
393 		auto values = e.values.map!(v => visit(v)).array();
394 
395 		// The type of the first element determine the type of the array.
396 		auto type =
397 			values.length > 0 ? values[0].type : Type.get(BuiltinType.Void);
398 
399 		// Cast all the value to the proper type.
400 		values = values.map!(v => buildImplicitCast(pass, v.location, type, v))
401 			.array();
402 
403 		return build!ArrayLiteral(e.location, type.getSlice(), values);
404 	}
405 
406 	Expression buildArgument(Expression arg, ParamType pt) {
407 		if (pt.isRef && !canConvert(arg.type.qualifier, pt.qualifier)) {
408 			return getError(arg, "Can't pass argument ("
409 				~ arg.type.toString(context) ~ ") by ref to "
410 				~ pt.toString(context));
411 		}
412 
413 		arg = buildImplicitCast(pass, arg.location, pt.getType(), arg);
414 
415 		// Test if we can pass by ref.
416 		if (pt.isRef && !arg.isLvalue) {
417 			return getError(arg, "Argument isn't a lvalue");
418 		}
419 
420 		return arg;
421 	}
422 
423 	enum MatchLevel {
424 		Not,
425 		TypeConvert,
426 		QualifierConvert,
427 		Exact,
428 	}
429 
430 	// TODO: deduplicate.
431 	private auto matchArgument(Expression arg, ParamType param) {
432 		if (param.isRef && !canConvert(arg.type.qualifier, param.qualifier)) {
433 			return MatchLevel.Not;
434 		}
435 
436 		auto flavor = implicitCastFrom(pass, arg.type, param.getType());
437 
438 		// test if we can pass by ref.
439 		if (param.isRef && !(flavor >= CastKind.Bit && arg.isLvalue)) {
440 			return MatchLevel.Not;
441 		}
442 
443 		return matchLevel(flavor);
444 	}
445 
446 	// TODO: deduplicate.
447 	private auto matchArgument(ParamType type, ParamType param) {
448 		if (param.isRef && !canConvert(type.qualifier, param.qualifier)) {
449 			return MatchLevel.Not;
450 		}
451 
452 		auto flavor = implicitCastFrom(pass, type.getType(), param.getType());
453 
454 		// test if we can pass by ref.
455 		if (param.isRef && !(flavor >= CastKind.Bit && type.isRef)) {
456 			return MatchLevel.Not;
457 		}
458 
459 		return matchLevel(flavor);
460 	}
461 
462 	private auto matchLevel(CastKind flavor) {
463 		final switch (flavor) with (CastKind) {
464 			case Invalid:
465 				return MatchLevel.Not;
466 
467 			case IntToPtr, PtrToInt, Down, IntToBool, Trunc:
468 				assert(0, "Not an implicit cast !");
469 
470 			case UPad, SPad, Bit:
471 				return MatchLevel.TypeConvert;
472 
473 			case Qual:
474 				return MatchLevel.QualifierConvert;
475 
476 			case Exact:
477 				return MatchLevel.Exact;
478 		}
479 	}
480 
481 	private Expression getContext(Location location, Function f) in {
482 		assert(f.step >= Step.Signed);
483 	} do {
484 		import d.semantic.closure;
485 		auto ctx = ContextFinder(pass).visit(f);
486 		return build!ContextExpression(location, ctx);
487 	}
488 
489 	Expression getFrom(Location location, Function f) {
490 		scheduler.require(f, Step.Signed);
491 
492 		Expression[] ctxs;
493 		ctxs.reserve(f.hasThis + f.hasContext);
494 		if (f.hasContext) {
495 			ctxs ~= getContext(location, f);
496 		}
497 
498 		if (f.hasThis) {
499 			ctxs ~= getThis(location);
500 		}
501 
502 		return getFromImpl(location, f, ctxs);
503 	}
504 
505 	Expression getFrom(Location location, Expression thisExpr, Function f) {
506 		scheduler.require(f, Step.Signed);
507 
508 		Expression[] ctxs;
509 		ctxs.reserve(f.hasContext + 1);
510 
511 		if (f.hasContext) {
512 			ctxs ~= getContext(location, f);
513 		}
514 
515 		ctxs ~= thisExpr;
516 		return getFromImpl(location, f, ctxs);
517 	}
518 
519 	private Expression getFromImpl(Location location, Function f,
520 	                               Expression[] ctxs) in {
521 		assert(f.step >= Step.Signed);
522 		assert(ctxs.length >= f.hasContext + f.hasThis);
523 	} do {
524 		foreach (i, ref c; ctxs) {
525 			c = buildArgument(c, f.type.parameters[i]);
526 		}
527 
528 		auto e = (ctxs.length == 0)
529 			? new FunctionExpression(location, f)
530 			: build!DelegateExpression(location, ctxs, f);
531 
532 		// If this is not a property, things are straigforward.
533 		if (!f.isProperty) {
534 			return e;
535 		}
536 
537 		assert(!f.hasContext);
538 		if (f.params.length != ctxs.length - f.hasContext) {
539 			return getError(e, "Invalid number of argument for @property "
540 				~ f.name.toString(context));
541 		}
542 
543 		Expression[] args;
544 		return build!CallExpression(location, f.type.returnType.getType(), e,
545 		                            args);
546 	}
547 
548 	Expression visit(AstCallExpression c) {
549 		import std.algorithm, std.array;
550 		auto args = c.args.map!(a => visit(a)).array();
551 
552 		// FIXME: Have a ThisCallExpression.
553 		auto te = cast(ThisExpression) c.callee;
554 		if (te is null) {
555 			return handleCall(c.location, visit(c.callee), args);
556 		}
557 
558 		// FIXME: check if we are in a constructor.
559 		auto t = thisType.getType().getCanonical();
560 		if (!t.isAggregate()) {
561 			assert(0, "ctor on non aggregate not implemented");
562 		}
563 
564 		auto loc = c.callee.location;
565 		auto thisExpr = getThis(loc);
566 
567 		auto ctor = findCtor(c.location, loc, thisExpr, args);
568 		auto thisKind = ctor.type.asFunctionType().contexts[0].paramKind;
569 		auto call = callCallable(c.location, ctor, args);
570 
571 		final switch (thisKind) with (ParamKind) {
572 			case Regular:
573 				// Value type, by value.
574 				return build!BinaryExpression(c.location, thisExpr.type,
575 				                              BinaryOp.Assign, thisExpr, call);
576 
577 			case Final:
578 				// Classes.
579 				return call;
580 
581 			case Ref:
582 				// Value type, by ref.
583 				return build!BinaryExpression(c.location, thisExpr.type,
584 				                              BinaryOp.Comma, call, thisExpr);
585 		}
586 	}
587 
588 	Expression visit(IdentifierCallExpression c) {
589 		import std.algorithm, std.array;
590 		auto args = c.args.map!(a => visit(a)).array();
591 
592 		// XXX: Why are doing this here ?
593 		// Shouldn't this be done in the identifier module ?
594 		Expression postProcess(T)(T identified) {
595 			static if (is(T : Expression)) {
596 				return handleCall(c.location, identified, args);
597 			} else {
598 				static if (is(T : Symbol)) {
599 					if (auto s = cast(OverloadSet) identified) {
600 						return callOverloadSet(c.location, s, args);
601 					}
602 
603 					if (auto t = cast(Template) identified) {
604 						auto callee = handleIFTI(c.location, t, args);
605 						return callCallable(c.location, callee, args);
606 					}
607 				}
608 
609 				static if (is(T : Type)) {
610 					return callType(c.location, c.callee.location, identified,
611 					                args);
612 				} else {
613 					return getError(
614 						identified, c.location,
615 						c.callee.toString(pass.context) ~ " isn't callable");
616 				}
617 			}
618 		}
619 
620 		import d.ast.identifier, d.semantic.identifier;
621 		if (auto tidi = cast(TemplateInstantiation) c.callee) {
622 			// XXX: For some reason this need to be passed a lambda.
623 			return IdentifierResolver(pass).build(tidi, args)
624 				.apply!(i => postProcess(i))();
625 		}
626 
627 		// XXX: For some reason this need to be passed a lambda.
628 		return IdentifierResolver(pass).build(c.callee)
629 			.apply!((i => postProcess(i)))();
630 	}
631 
632 	Expression visit(TypeCallExpression e) {
633 		import d.semantic.type;
634 		auto t = TypeVisitor(pass).visit(e.type);
635 
636 		import std.algorithm, std.array;
637 		auto args = e.args.map!(a => visit(a)).array();
638 
639 		return callType(e.location, e.location, t, args);
640 	}
641 
642 	private Expression callType(Location location, Location calleeLoc,
643 	                            Type callee, Expression[] args) {
644 		auto t = callee.getCanonical();
645 		switch (t.kind) with (TypeKind) {
646 			case Builtin:
647 				if (args.length == 1) {
648 					return buildImplicitCast(pass, location, t, args[0]);
649 				}
650 
651 				return getError(t, location, "Expected one argument");
652 
653 			case Struct:
654 				auto s = t.dstruct;
655 				scheduler.require(s, Step.Signed);
656 
657 				import d.semantic.defaultinitializer;
658 				auto di = InstanceBuilder(pass, calleeLoc).visit(s);
659 				if (s.isSmall) {
660 					return callCtor(location, calleeLoc, di, args);
661 				}
662 
663 				auto thisExpr = getTemporary(di);
664 				return build!BinaryExpression(
665 					location, t, BinaryOp.Comma,
666 					callCtor(location, calleeLoc, thisExpr, args), thisExpr);
667 
668 			default:
669 				return getError(t, location, "Cannot build this type");
670 		}
671 	}
672 
673 	private Expression callCtor(Location location, Location calleeLoc,
674 	                            Expression thisExpr, Expression[] args) in {
675 		assert(thisExpr.type.isAggregate());
676 	} do {
677 		auto ctor = findCtor(location, calleeLoc, thisExpr, args);
678 		return callCallable(location, ctor, args);
679 	}
680 
681 	// XXX: factorize with NewExpression
682 	private Expression findCtor(Location location, Location calleeLoc,
683 	                            Expression thisExpr, Expression[] args) in {
684 		assert(thisExpr.type.isAggregate(),
685 		       thisExpr.toString(context) ~ " is not an aggregate");
686 	} do {
687 		auto agg = thisExpr.type.aggregate;
688 
689 		import source.name, d.semantic.identifier;
690 		return IdentifierResolver(pass)
691 			.resolveIn(location, agg, BuiltinName!"__ctor")
692 			.apply!(delegate Expression(i) {
693 				alias T = typeof(i);
694 				static if (is(T : Symbol)) {
695 					if (auto f = cast(Function) i) {
696 						return getFrom(calleeLoc, thisExpr, f);
697 					}
698 
699 					if (auto s = cast(OverloadSet) i) {
700 						// FIXME: overload resolution doesn't do alias this
701 						// or vrp trunc, so we need a workaround here.
702 						if (s.set.length == 1) {
703 							if (auto f = cast(Function) s.set[0]) {
704 								return getFrom(calleeLoc, thisExpr, f);
705 							}
706 						}
707 
708 						import std.algorithm, std.array;
709 						return chooseOverload(
710 							location, s.set.map!(delegate Expression(s) {
711 								if (auto f = cast(Function) s) {
712 									return getFrom(calleeLoc, thisExpr, f);
713 								}
714 
715 								// XXX: Template ??!?!!?
716 								assert(0, "Not a constructor");
717 							}).array(), args);
718 					}
719 				}
720 
721 				return getError(
722 					i, location,
723 					agg.name.toString(pass.context) ~ " isn't callable");
724 			})();
725 	}
726 
727 	private
728 	Expression handleIFTI(Location location, Template t, Expression[] args) {
729 		import d.semantic.dtemplate;
730 		TemplateArgument[] targs;
731 		targs.length = t.parameters.length;
732 
733 		auto i = TemplateInstancier(pass).instanciate(location, t, [], args);
734 		scheduler.require(i);
735 
736 		import d.semantic.identifier;
737 		return IdentifierResolver(pass).buildIn(location, i, t.name)
738 			.apply!(delegate Expression(identified) {
739 				alias T = typeof(identified);
740 				static if (is(T : Expression)) {
741 					return identified;
742 				} else {
743 					return getError(
744 						identified, location,
745 						t.name.toString(pass.context) ~ " isn't callable");
746 				}
747 			})();
748 	}
749 
750 	private Expression callOverloadSet(Location location, OverloadSet s,
751 	                                   Expression[] args) {
752 		import std.algorithm, std.array;
753 		return callCallable(location, chooseOverload(location, s.set.map!((s) {
754 			pass.scheduler.require(s, Step.Signed);
755 			if (auto f = cast(Function) s) {
756 				return getFrom(location, f);
757 			} else if (auto t = cast(Template) s) {
758 				return handleIFTI(location, t, args);
759 			}
760 
761 			throw new CompileException(
762 				s.location,
763 				typeid(s).toString() ~ " is not supported in overload set");
764 		}).array(), args), args);
765 	}
766 
767 	private static bool checkArgumentCount(bool isVariadic, size_t argCount,
768 	                                       size_t paramCount) {
769 		return isVariadic ? argCount >= paramCount : argCount == paramCount;
770 	}
771 
772 	// XXX: Take a range instead of an array.
773 	private
774 	Expression chooseOverload(Location location, Expression[] candidates,
775 	                          Expression[] args) {
776 		import std.algorithm, std.range;
777 		auto cds =
778 			candidates.map!(e => findCallable(location, e, args)).filter!((e) {
779 				auto t = e.type.getCanonical();
780 				assert(
781 					t.kind == TypeKind.Function,
782 					e.type.toString(pass.context) ~ " is not a function type");
783 
784 				auto ft = t.asFunctionType();
785 				return checkArgumentCount(ft.isVariadic, args.length,
786 				                          ft.parameters.length);
787 			});
788 
789 		auto level = MatchLevel.Not;
790 		Expression match;
791 		CandidateLoop: foreach (candidate; cds) {
792 			auto t = candidate.type.getCanonical();
793 			assert(t.kind == TypeKind.Function,
794 			       "We should have filtered function at this point.");
795 
796 			auto funType = t.asFunctionType();
797 
798 			auto candidateLevel = MatchLevel.Exact;
799 			foreach (arg, param; lockstep(args, funType.parameters)) {
800 				auto argLevel = matchArgument(arg, param);
801 
802 				// If we don't match high enough.
803 				if (argLevel < level) {
804 					continue CandidateLoop;
805 				}
806 
807 				final switch (argLevel) with (MatchLevel) {
808 					case Not:
809 						// This function don't match, go to next one.
810 						continue CandidateLoop;
811 
812 					case TypeConvert, QualifierConvert:
813 						candidateLevel = min(candidateLevel, argLevel);
814 						continue;
815 
816 					case Exact:
817 						// Go to next argument
818 						continue;
819 				}
820 			}
821 
822 			if (candidateLevel > level) {
823 				level = candidateLevel;
824 				match = candidate;
825 			} else if (candidateLevel == level) {
826 				// Check for specialisation.
827 				auto mt = match.type.getCanonical();
828 				assert(mt.kind == TypeKind.Function,
829 				       "We should have filtered function at this point.");
830 
831 				auto prange = lockstep(funType.parameters,
832 				                       mt.asFunctionType().parameters);
833 
834 				bool candidateFail;
835 				bool matchFail;
836 				foreach (param, matchParam; prange) {
837 					if (matchArgument(param, matchParam) == MatchLevel.Not) {
838 						candidateFail = true;
839 					}
840 
841 					if (matchArgument(matchParam, param) == MatchLevel.Not) {
842 						matchFail = true;
843 					}
844 				}
845 
846 				if (matchFail == candidateFail) {
847 					return getError(candidate, location,
848 					                "ambiguous function call.");
849 				}
850 
851 				if (matchFail) {
852 					match = candidate;
853 				}
854 			}
855 		}
856 
857 		if (!match) {
858 			return new CompileError(location, "No candidate for function call")
859 				.expression;
860 		}
861 
862 		return match;
863 	}
864 
865 	private Expression findCallable(Location location, Expression callee,
866 	                                Expression[] args) {
867 		if (auto asPolysemous = cast(PolysemousExpression) callee) {
868 			return chooseOverload(location, asPolysemous.expressions, args);
869 		}
870 
871 		auto type = callee.type.getCanonical();
872 		if (type.kind == TypeKind.Function) {
873 			return callee;
874 		}
875 
876 		import std.algorithm, std.array;
877 		import d.semantic.aliasthis;
878 		auto ar = AliasThisResolver!((identified) {
879 			alias T = typeof(identified);
880 			static if (is(T : Expression)) {
881 				return findCallable(location, identified, args);
882 			} else {
883 				return cast(Expression) null;
884 			}
885 		})(pass);
886 
887 		auto results = ar.resolve(callee)
888 			.filter!(e => e !is null && typeid(e) !is typeid(ErrorExpression))
889 			.array();
890 
891 		if (results.length == 1) {
892 			return results[0];
893 		}
894 
895 		return getError(callee, location,
896 		                "You must call function or delegates, not "
897 			                ~ callee.type.toString(context));
898 	}
899 
900 	private Expression handleCall(Location location, Expression callee,
901 	                              Expression[] args) {
902 		return
903 			callCallable(location, findCallable(location, callee, args), args);
904 	}
905 
906 	// XXX: This assume that calable is the right one,
907 	// but not all call sites do the check.
908 	private Expression callCallable(Location location, Expression callee,
909 	                                Expression[] args) in {
910 		auto k = callee.type.getCanonical().kind;
911 		assert(k == TypeKind.Function || k == TypeKind.Error,
912 		       callee.toString(context));
913 	} do {
914 		auto t = callee.type.getCanonical();
915 		if (t.kind == TypeKind.Error) {
916 			return callee;
917 		}
918 
919 		auto f = t.asFunctionType();
920 
921 		auto paramTypes = f.parameters;
922 		auto returnType = f.returnType;
923 
924 		// If we don't have enough parameters, try to find default
925 		// values in the function declaration.
926 		if (args.length < paramTypes.length) {
927 			Function fun;
928 			if (auto fe = cast(FunctionExpression) callee) {
929 				fun = fe.fun;
930 			} else if (auto dge = cast(DelegateExpression) callee) {
931 				fun = dge.method;
932 			} else {
933 				// Can't find the function, error.
934 				return getError(callee, location, "Insuffiscient parameters");
935 			}
936 
937 			auto start = args.length + f.contexts.length;
938 			auto stop = paramTypes.length + f.contexts.length;
939 			auto params = fun.params[start .. stop];
940 			foreach (p; params) {
941 				if (p.value is null) {
942 					return
943 						getError(callee, location, "Insuffiscient parameters");
944 				}
945 
946 				args ~= p.value;
947 			}
948 		} else if (args.length > paramTypes.length && !f.isVariadic) {
949 			return getError(callee, location, "Too much parameters");
950 		}
951 
952 		import std.range;
953 		foreach (ref arg, pt; lockstep(args, paramTypes)) {
954 			arg = buildArgument(arg, pt);
955 		}
956 
957 		// If this is an intrinsic, create an intrinsic expression
958 		if (auto fe = cast(FunctionExpression) callee) {
959 			if (auto i = fe.fun.intrinsicID) {
960 				return build!IntrinsicExpression(location, returnType.getType(),
961 				                                 i, args);
962 			}
963 		}
964 
965 		return
966 			build!CallExpression(location, returnType.getType(), callee, args);
967 	}
968 
969 	// XXX: factorize with findCtor
970 	Expression visit(AstNewExpression e) {
971 		import std.algorithm, std.array;
972 		auto args = e.args.map!(a => visit(a)).array();
973 
974 		import d.semantic.type;
975 		auto type = TypeVisitor(pass).visit(e.type);
976 
977 		import d.semantic.defaultinitializer;
978 		auto di = NewBuilder(pass, e.location).visit(type);
979 		auto hackForDg = (&di)[0 .. 1];
980 
981 		import source.name, d.semantic.identifier;
982 		auto ctor = IdentifierResolver(pass)
983 			.resolveIn(e.location, type, BuiltinName!"__ctor")
984 			.apply!(delegate Function(identified) {
985 				static if (is(typeof(identified) : Symbol)) {
986 					if (auto f = cast(Function) identified) {
987 						pass.scheduler.require(f, Step.Signed);
988 						return f;
989 					}
990 
991 					if (auto s = cast(OverloadSet) identified) {
992 						auto m = chooseOverload(
993 							e.location, s.set.map!(delegate Expression(s) {
994 								if (auto f = cast(Function) s) {
995 									return new DelegateExpression(e.location,
996 									                              hackForDg, f);
997 								}
998 
999 								assert(0, "not a constructor");
1000 							}).array(), args);
1001 
1002 						// XXX: find a clean way to achieve this.
1003 						return (cast(DelegateExpression) m).method;
1004 					}
1005 				}
1006 
1007 				assert(0, "Gimme some construtor !");
1008 			})();
1009 
1010 		// First parameter is compiler magic.
1011 		auto parameters = ctor.type.parameters[1 .. $];
1012 
1013 		import std.range;
1014 		assert(args.length >= parameters.length);
1015 		foreach (ref arg, pt; lockstep(args, parameters)) {
1016 			arg = buildArgument(arg, pt);
1017 		}
1018 
1019 		if (type.getCanonical().kind != TypeKind.Class) {
1020 			type = type.getPointer();
1021 		}
1022 
1023 		return build!NewExpression(e.location, type, di, ctor, args);
1024 	}
1025 
1026 	Expression getThis(Location location) {
1027 		import source.name, d.semantic.identifier;
1028 		auto thisExpr = IdentifierResolver(pass)
1029 			.build(location, BuiltinName!"this")
1030 			.apply!(delegate Expression(identified) {
1031 				static if (is(typeof(identified) : Expression)) {
1032 					return identified;
1033 				} else {
1034 					return new CompileError(
1035 							location, "Cannot find a suitable this pointer")
1036 						.expression;
1037 				}
1038 			})();
1039 
1040 		return buildImplicitCast(pass, location, thisType.getType(), thisExpr);
1041 	}
1042 
1043 	Expression visit(ThisExpression e) {
1044 		return getThis(e.location);
1045 	}
1046 
1047 	Expression getIndex(Location location, Expression indexed,
1048 	                    Expression index) {
1049 		auto t = indexed.type.getCanonical();
1050 		if (!t.hasElement) {
1051 			return getError(indexed, location,
1052 			                "Can't index " ~ indexed.type.toString(context));
1053 		}
1054 
1055 		index = buildImplicitCast(pass, location, pass.object.getSizeT().type,
1056 		                          index);
1057 
1058 		// Make sure we create a temporary for rvalue indices.
1059 		// XXX: Should this be done in the backend ?
1060 		if (t.kind == TypeKind.Array && !indexed.isLvalue) {
1061 			indexed = getTemporary(indexed);
1062 		}
1063 
1064 		return build!IndexExpression(location, t.element, indexed, index);
1065 	}
1066 
1067 	Expression visit(AstIndexExpression e) {
1068 		auto indexed = visit(e.indexed);
1069 
1070 		import std.algorithm, std.array;
1071 		auto arguments = e.arguments.map!(e => visit(e)).array();
1072 		assert(arguments.length == 1,
1073 		       "Multiple argument index are not supported");
1074 
1075 		return getIndex(e.location, indexed, arguments[0]);
1076 	}
1077 
1078 	Expression visit(AstSliceExpression e) {
1079 		// TODO: check if it is valid.
1080 		auto sliced = visit(e.sliced);
1081 
1082 		auto t = sliced.type.getCanonical();
1083 		if (!t.hasElement) {
1084 			return getError(sliced, e.location,
1085 			                "Can't slice " ~ t.toString(context));
1086 		}
1087 
1088 		assert(e.first.length == 1 && e.second.length == 1);
1089 
1090 		auto first = visit(e.first[0]);
1091 		auto second = visit(e.second[0]);
1092 
1093 		return build!SliceExpression(e.location, t.element.getSlice(), sliced,
1094 		                             first, second);
1095 	}
1096 
1097 	private Expression handleTypeid(Location location, Expression e) {
1098 		auto c = e.type.getCanonical();
1099 		if (c.kind == TypeKind.Class) {
1100 			auto classInfo = pass.object.getClassInfo();
1101 			return
1102 				build!DynamicTypeidExpression(location, Type.get(classInfo), e);
1103 		}
1104 
1105 		return getTypeInfo(location, e.type);
1106 	}
1107 
1108 	auto getTypeInfo(Location location, Type t) {
1109 		t = t.getCanonical();
1110 		if (t.kind == TypeKind.Class) {
1111 			return getClassInfo(location, t.dclass);
1112 		}
1113 
1114 		alias StaticTypeidExpression = d.ir.expression.StaticTypeidExpression;
1115 		return build!StaticTypeidExpression(
1116 			location, Type.get(pass.object.getTypeInfo()), t);
1117 	}
1118 
1119 	auto getClassInfo(Location location, Class c) {
1120 		alias StaticTypeidExpression = d.ir.expression.StaticTypeidExpression;
1121 		return build!StaticTypeidExpression(
1122 			location, Type.get(pass.object.getClassInfo()), Type.get(c));
1123 	}
1124 
1125 	Expression visit(AstTypeidExpression e) {
1126 		return handleTypeid(e.location, visit(e.argument));
1127 	}
1128 
1129 	Expression visit(AstStaticTypeidExpression e) {
1130 		import d.semantic.type;
1131 		return getTypeInfo(e.location, TypeVisitor(pass).visit(e.argument));
1132 	}
1133 
1134 	Expression visit(IdentifierTypeidExpression e) {
1135 		import d.semantic.identifier;
1136 		return IdentifierResolver(pass).build(e.argument)
1137 			.apply!(delegate Expression(identified) {
1138 				alias T = typeof(identified);
1139 				static if (is(T : Type)) {
1140 					return getTypeInfo(e.location, identified);
1141 				} else static if (is(T : Expression)) {
1142 					return handleTypeid(e.location, identified);
1143 				} else {
1144 					return getError(identified, e.location,
1145 					                "Can't get typeid of "
1146 						                ~ e.argument.toString(pass.context));
1147 				}
1148 			})();
1149 	}
1150 
1151 	Expression visit(IdentifierExpression e) {
1152 		import d.semantic.identifier;
1153 		return IdentifierResolver(pass).build(e.identifier)
1154 			.apply!(delegate Expression(identified) {
1155 				alias T = typeof(identified);
1156 				static if (is(T : Expression)) {
1157 					return identified;
1158 				} else {
1159 					static if (is(T : Symbol)) {
1160 						if (auto s = cast(OverloadSet) identified) {
1161 							return buildPolysemous(e.location, s);
1162 						}
1163 					}
1164 
1165 					return getError(identified, e.location,
1166 					                e.identifier.toString(pass.context)
1167 						                ~ " isn't an expression");
1168 				}
1169 			})();
1170 	}
1171 
1172 	private Expression buildPolysemous(Location location, OverloadSet s) {
1173 		import std.algorithm, std.array;
1174 		import d.semantic.identifier;
1175 		auto exprs = s.set.map!(s => IdentifierResolver(pass)
1176 			.postProcess(location, s).apply!(delegate Expression(identified) {
1177 				alias T = typeof(identified);
1178 				static if (is(T : Expression)) {
1179 					return identified;
1180 				} else static if (is(T : Type)) {
1181 					assert(0, "Type can't be overloaded");
1182 				} else {
1183 					// TODO: handle templates.
1184 					throw new CompileException(
1185 						identified.location, typeid(identified).toString()
1186 							~ " is not supported in overload set");
1187 				}
1188 			})()).array();
1189 		return new PolysemousExpression(location, exprs);
1190 	}
1191 
1192 	import d.ast.declaration, d.ast.statement;
1193 	private auto handleDgs(Location location, string prefix, ParamDecl[] params,
1194 	                       bool isVariadic, BlockStatement fbody) {
1195 		// FIXME: can still collide with mixins,
1196 		// but that should rare enough for now.
1197 		import std.conv;
1198 		auto offset = location.getFullLocation(context).getStartOffset();
1199 		auto name = context.getName(prefix ~ offset.to!string());
1200 
1201 		auto d = new FunctionDeclaration(
1202 			location, defaultStorageClass,
1203 			AstType.getAuto().getParamType(ParamKind.Regular), name, params,
1204 			isVariadic, fbody);
1205 
1206 		auto f =
1207 			new Function(location, currentScope, FunctionType.init, name, []);
1208 
1209 		f.hasContext = true;
1210 
1211 		import d.semantic.symbol;
1212 		SymbolAnalyzer(pass).analyze(d, f);
1213 		scheduler.require(f);
1214 
1215 		return getFrom(location, f);
1216 	}
1217 
1218 	Expression visit(DelegateLiteral e) {
1219 		return handleDgs(e.location, "__dg", e.params, e.isVariadic, e.fbody);
1220 	}
1221 
1222 	Expression visit(Lambda e) {
1223 		auto v = e.value;
1224 		return handleDgs(
1225 			e.location,
1226 			"__lambda",
1227 			e.params,
1228 			false,
1229 			new BlockStatement(v.location, [new ReturnStatement(v.location, v)])
1230 		);
1231 	}
1232 
1233 	import d.ast.conditional;
1234 	Expression visit(Mixin!AstExpression e) {
1235 		import d.semantic.evaluator;
1236 		auto str = evalString(visit(e.value));
1237 		auto pos = context.registerMixin(e.location, str ~ "\0");
1238 
1239 		import source.dlexer;
1240 		auto trange = lex(pos, context);
1241 
1242 		import d.parser.base, d.parser.expression;
1243 		trange.match(TokenType.Begin);
1244 		return visit(trange.parseExpression());
1245 	}
1246 }