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