1 /// Copyright: Copyright (c) 2017-2019 Andrey Penechko.
2 /// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
3 /// Authors: Andrey Penechko.
4 
5 // inside struct method supported:
6 // foo;
7 // foo();
8 // this.foo;
9 // this.foo();
10 // in static function:
11 // s.foo;
12 // s.foo();
13 module vox.fe.ast.expr.call;
14 
15 import vox.all;
16 
17 enum CallExprFlags : ushort
18 {
19 	hasNamedArgs = AstFlags.userFlag << 0,
20 }
21 
22 @(AstType.expr_call)
23 struct CallExprNode {
24 	mixin ExpressionNodeData!(AstType.expr_call);
25 	ScopeIndex parentScope; // needed to resolve `this` pointer in member access
26 	AstIndex callee;
27 	AstNodes args;
28 	IrIndex[] argsValues;
29 
30 	bool hasNamedArgs() { return cast(bool)(flags & CallExprFlags.hasNamedArgs); }
31 }
32 
33 void print_call(CallExprNode* node, ref AstPrintState state)
34 {
35 	if (node.callee && node.callee.astType(state.context) == AstType.decl_function)
36 	{
37 		state.print("CALL ", state.context.idString(node.callee.get_node_id(state.context)));
38 	}
39 	else
40 	{
41 		state.print("CALL");
42 		print_ast(node.callee, state);
43 	}
44 	print_ast(node.args, state);
45 }
46 
47 void post_clone_call(CallExprNode* node, ref CloneState state)
48 {
49 	state.fixScope(node.parentScope);
50 	state.fixAstIndex(node.callee);
51 	state.fixAstNodes(node.args);
52 }
53 
54 void name_register_nested_call(CallExprNode* node, ref NameRegisterState state) {
55 	node.state = AstNodeState.name_register_nested;
56 	require_name_register(node.callee, state);
57 	require_name_register(node.args, state);
58 	node.state = AstNodeState.name_register_nested_done;
59 }
60 
61 void name_resolve_call(CallExprNode* node, ref NameResolveState state) {
62 	node.state = AstNodeState.name_resolve;
63 	require_name_resolve(node.callee, state);
64 	require_name_resolve(node.args, state);
65 	node.state = AstNodeState.name_resolve_done;
66 }
67 
68 // Get type from function declaration
69 void type_check_call(ref AstIndex callIndex, CallExprNode* node, ref TypeCheckState state)
70 {
71 	CompilationContext* c = state.context;
72 
73 	node.state = AstNodeState.type_check;
74 	scope(exit) node.state = AstNodeState.type_check_done;
75 
76 	AstNodes templateArgs;
77 	AstIndex callee = node.callee.get_effective_node(c);
78 
79 	start: switch (callee.astType(c))
80 	{
81 		// static function call
82 		case AstType.decl_function:
83 			auto func = callee.get!FunctionDeclNode(c);
84 			if (func.isMember) {
85 				// rewrite as method[](args) as method[](this, args)
86 				// let member_access handle everything else
87 				AstIndex thisName = c.appendAst!NameUseExprNode(node.loc, node.parentScope, CommonIds.id_this);
88 				require_name_resolve(thisName, c);
89 				node.args.putFront(c.arrayArena, thisName);
90 			}
91 			auto signature = func.signature.get!FunctionSignatureNode(c);
92 			return type_check_func_call(node, signature, func.id, state);
93 
94 		case AstType.decl_struct:
95 			require_type_check(callee, state, IsNested.no);
96 			return type_check_constructor_call(node, callee.get!StructDeclNode(c), state);
97 
98 		case AstType.expr_member:
99 			MemberExprNode* memberNode = callee.get!MemberExprNode(c);
100 			// Method call
101 			LookupResult res = lookupMember(callee, memberNode, state);
102 			if (res == LookupResult.success) {
103 				AstIndex memberIndex = memberNode.member(c);
104 
105 				if (memberNode.subType == MemberSubType.struct_templ_method) {
106 					memberIndex = get_template_instance(memberIndex, node.loc, templateArgs, state);
107 
108 					if (memberIndex == CommonAstNodes.node_error) {
109 						node.type = CommonAstNodes.type_error;
110 						return;
111 					}
112 				}
113 
114 				auto calleeType = memberIndex.get_type(c);
115 
116 				if (calleeType.isPointer)
117 				{
118 					TypeNode* base = calleeType.as_ptr.base.get_type(c);
119 					if (base.isFuncSignature)
120 					{
121 						auto signature = base.as_func_sig;
122 						return type_check_func_call(node, signature, memberNode.memberId(c), state);
123 					}
124 				}
125 
126 				node.callee = memberIndex;
127 
128 				auto signature = calleeType.as_func_sig;
129 				assert(signature);
130 				if (memberNode.member(c).get_node(c).isMember) {
131 					lowerThisArgument(signature, memberNode.aggregate, memberNode.loc, c);
132 					node.args.putFront(c.arrayArena, memberNode.aggregate);
133 				}
134 				return type_check_func_call(node, signature, memberNode.memberId(c), state);
135 			}
136 
137 			// UFCS call
138 			Identifier calleeName = memberNode.memberId(c);
139 			LookupResult ufcsRes = tryUFCSCall(callIndex, memberNode, state);
140 			if (ufcsRes == LookupResult.failure) {
141 				AstIndex objType = memberNode.aggregate.get_node_type(c);
142 				node.type = CommonAstNodes.type_error;
143 				c.error(node.loc, "`%s` has no member `%s`", objType.printer(c), c.idString(calleeName));
144 				return;
145 			}
146 			break;
147 
148 		case AstType.decl_var, AstType.decl_enum_member:
149 			// check if func ptr
150 			TypeNode* varType = callee.get_node_type(c).get_type(c);
151 			if (varType.isPointer)
152 			{
153 				TypeNode* base = varType.as_ptr.base.get_type(c);
154 				if (base.isFuncSignature)
155 				{
156 					auto signature = base.as_func_sig;
157 					return type_check_func_call(node, signature, callee.get_node_id(c), state);
158 				}
159 			}
160 			if (varType.isAlias)
161 			{
162 				if (callee.astType(c) == AstType.decl_var) goto default;
163 				auto enumMember = callee.get!EnumMemberDecl(c);
164 				node.callee = eval_static_expr_alias(enumMember.initializer, c);
165 				callee = node.callee; // used in case decl_function
166 				goto case AstType.decl_function;
167 			}
168 			goto default;
169 
170 		case AstType.expr_index:
171 			auto index = callee.get!IndexExprNode(c);
172 			AstIndex effective_array = index.array.get_effective_node(c);
173 			AstType array_ast_type = effective_array.astType(c);
174 
175 			require_type_check(index.indices, state);
176 
177 			if (array_ast_type == AstType.decl_template)
178 			{
179 				// template instantiation
180 				callee = get_template_instance(effective_array, node.loc, index.indices, state);
181 				if (callee == CommonAstNodes.node_error) {
182 					node.type = CommonAstNodes.type_error;
183 					return;
184 				}
185 				node.callee = callee;
186 
187 				switch(callee.astType(c)) {
188 					case AstType.decl_function:
189 					case AstType.decl_struct:
190 						goto start;
191 					default:
192 						c.internal_error(node.loc, "Unexpected template type %s", callee.astType(c));
193 				}
194 			}
195 
196 			if (array_ast_type == AstType.expr_member)
197 			{
198 				templateArgs = index.indices;
199 				callee = effective_array;
200 				node.callee = callee;
201 				goto case AstType.expr_member;
202 			}
203 
204 			goto case AstType.decl_var;
205 		case AstType.decl_template:
206 			auto templ = callee.get!TemplateDeclNode(c);
207 
208 			//writefln("%s %s", templ.isMember, templ.body.get_node(c).isMember);
209 
210 			if (templ.body.astType(c) != AstType.decl_function) {
211 				c.unrecoverable_error(node.loc, "Cannot call template of %s", templ.body.astType(c));
212 			}
213 
214 			c.assertf(!node.hasNamedArgs, node.loc, "Named arguments with variadics are not implemented");
215 
216 			auto templFunc = templ.body.get!FunctionDeclNode(c);
217 			auto templSignature = templFunc.signature.get!FunctionSignatureNode(c);
218 
219 			if (templ.isMember) {
220 				// rewrite as method[](args) as method[](this, args)
221 				// let member_access handle everything else
222 				AstIndex thisName = c.appendAst!NameUseExprNode(node.loc, node.parentScope, CommonIds.id_this);
223 				require_name_resolve(thisName, c);
224 				node.args.putFront(c.arrayArena, thisName);
225 			}
226 
227 			bool success;
228 			AstNodes types = doIfti(node.loc, templ, templSignature, node.args, success, state);
229 			if (!success)
230 				c.unrecoverable_error(node.loc, "Cannot infer template arguments from runtime arguments");
231 
232 			callee = get_template_instance(callee, node.loc, types, state);
233 			node.callee = callee;
234 
235 			if (callee == CommonAstNodes.node_error) {
236 				node.type = CommonAstNodes.type_error;
237 				return;
238 			}
239 
240 			auto func = callee.get!FunctionDeclNode(c);
241 			auto signature = func.signature.get!FunctionSignatureNode(c);
242 			return type_check_func_call(node, signature, func.id, state);
243 		default:
244 			// unknown / unimplemented case
245 			node.type = CommonAstNodes.type_error;
246 			c.error(node.loc, "Cannot call %s", get_node_kind_name(callee, c));
247 			//c.internal_error(node.loc,
248 			//	"Only direct function calls are supported right now");
249 			return;
250 	}
251 }
252 
253 
254 // Returns inferred template parameters
255 // args needs to be ref, because type-check needs it to be ref
256 AstNodes doIfti(TokenIndex loc, TemplateDeclNode* templ, FunctionSignatureNode* sig, ref AstNodes rt_args, out bool success, ref TypeCheckState state)
257 {
258 	// - run through all provided runtime args
259 	// - get type of runtime parameter, if it is template type arg (T or T... here), then
260 	//   - if it is variadic template parameter T..., this and all subsequent variadic runtime argument types are appended
261 	//     after non-variadic template parameters, then continue walking non-variadics
262 	//   - otherwise it is type parameter T
263 	//     - if no type is given yet, assign runtime arg type
264 	//     - otherwise find common type between two
265 	// - at the end run through all template args, and error if any arg is not inferred.
266 
267 	// signature has 0 or 1 expanded parameter
268 	// template has 0 or 1 variadic parameter
269 
270 	CompilationContext* c = state.context;
271 
272 	AstNodes ct_params = templ.parameters;
273 	AstNodes rt_params = sig.parameters;
274 	auto numRtParams = rt_params.length;
275 	auto numCtParams = ct_params.length;
276 	auto numRtArgs = rt_args.length;
277 
278 	//writefln("numRtParams %s, numCtParams %s, numRtArgs %s, sig.hasExpandedParam %s, templ.hasVariadic %s",
279 	//		numRtParams, numCtParams, numRtArgs, sig.hasExpandedParam, templ.hasVariadic);
280 
281 	// array of inferred types (TODO: not only types)
282 	AstNodes inferredTemplArgs;
283 	success = true;
284 	if (numCtParams == 0) return inferredTemplArgs;
285 
286 	HashMap!(Identifier, AstIndex, Identifier.init) paramNames;
287 
288 	inferredTemplArgs.reserve(c.arrayArena, max(rt_args.length, ct_params.length));
289 
290 	foreach(uint i; 0..ct_params.length)
291 	{
292 		auto ctParam = ct_params[i].get!TemplateParamDeclNode(c);
293 		paramNames.put(c.arrayArena, ctParam.id, ct_params[i]);
294 		if (ctParam.isVariadic) break; // skip variadic and the rest of params
295 		inferredTemplArgs.put(c.arrayArena, AstIndex());
296 	}
297 
298 	void reportCorrectExpandedParam(TokenIndex loc, Identifier rt_param_id)
299 	{
300 		if (templ.hasVariadic) {
301 			uint variadicIndex = templ.numParamsBeforeVariadic;
302 			auto ctParam = ct_params[variadicIndex].get!TemplateParamDeclNode(c);
303 			c.error(loc, "Should be `%s... %s`", c.idString(ctParam.id), c.idString(rt_param_id));
304 		}
305 	}
306 
307 	if (templ.hasVariadic)
308 		c.assertf(templ.numParamsBeforeVariadic+1 == numCtParams, loc, "TODO: parameters after variadic template parameter");
309 
310 	if (sig.hasExpandedParam)
311 	{
312 		if (!templ.hasVariadic) {
313 			uint variadicIndex = sig.numParamsBeforeVariadic;
314 			auto param = sig.parameters[variadicIndex].get!VariableDeclNode(c);
315 			c.unrecoverable_error(param.loc, "Variadic parameters are not implemented");
316 		}
317 	}
318 	else
319 	{
320 		if (numRtParams != numRtArgs)
321 		{
322 			foreach(AstIndex idx; rt_params) {
323 				VariableDeclNode* rt_param = idx.get!VariableDeclNode(c);
324 				AstNode* rt_type = rt_param.type.get_node(c);
325 				if (rt_type.astType != AstType.expr_name_use) continue;
326 				auto typeName = rt_type.as!NameUseExprNode(c);
327 				Identifier typeId = typeName.id(c);
328 				AstIndex symIndex = paramNames.get(typeId, AstIndex.init);
329 				if (!symIndex) continue;
330 				auto ctParam = symIndex.get!TemplateParamDeclNode(c);
331 				if (ctParam.isVariadic) {
332 					reportCorrectExpandedParam(rt_type.loc, rt_param.id);
333 					break;
334 				}
335 			}
336 
337 			c.unrecoverable_error(loc,
338 				"Cannot infer template parameters. Number of runtime arguments (%s) does not match number of function parameters (%s)",
339 				numRtArgs, numRtParams);
340 		}
341 	}
342 
343 	void processTemplatedArg(AstIndex argTypeIndex, TemplateParamDeclNode* ctParam)
344 	{
345 		//writefln("ct_arg%s %s <- rt_arg %s",
346 		//	ctParam.index, c.idString(ctParam.id),
347 		//	argTypeIndex.printer(c));
348 
349 		if (inferredTemplArgs[ctParam.index].isUndefined)
350 		{
351 			// we found first use of template param. Assign type
352 			inferredTemplArgs[ctParam.index] = argTypeIndex;
353 		}
354 		else if (same_type(inferredTemplArgs[ctParam.index], argTypeIndex, c))
355 		{
356 			// ok
357 		}
358 		else
359 		{
360 			// calculate common type
361 			CommonTypeResult res = calcCommonType(inferredTemplArgs[ctParam.index], argTypeIndex, AstIndex(), AstIndex(), c);
362 			if (res.commonType.isErrorType) {
363 				c.error(loc, "Cannot infer template parameter %s, from argument types %s and %s",
364 					c.idString(ctParam.id),
365 					inferredTemplArgs[ctParam.index].printer(c),
366 					argTypeIndex.printer(c),
367 					);
368 				success = false;
369 			}
370 			inferredTemplArgs[ctParam.index] = res.commonType;
371 		}
372 	}
373 
374 	void processVariadicRtArgs(size_t group1_size)
375 	{
376 		uint group3_size = cast(uint)(numRtParams - group1_size - 1 - sig.numDefaultArgs);
377 		uint rt_group12_size = cast(uint)(numRtArgs - group3_size);
378 		uint rt_group2_size = cast(uint)(numRtArgs - group1_size - group3_size);
379 		//writefln("groups 1 %s 2 %s 3 %s 4 %s", group1_size, rt_group2_size, group3_size, sig.numDefaultArgs);
380 
381 		// group 2
382 		foreach(size_t i; group1_size..rt_group12_size)
383 		{
384 			require_type_check(rt_args[i], state); // do not cache args, because require_type_check may modify it
385 			AstIndex argTypeIndex = rt_args[i].get_expr_type(c);
386 			inferredTemplArgs.put(c.arrayArena, argTypeIndex);
387 		}
388 
389 		// group 3
390 		foreach(size_t i; rt_group12_size..numRtArgs)
391 		{
392 			require_type_check(rt_args[i], state); // do not cache args, because require_type_check may modify it
393 			AstIndex argTypeIndex = rt_args[i].get_expr_type(c);
394 			uint rtParamIndex = cast(uint)(i - rt_group2_size + 1); // 1 skips variadic param
395 
396 			AstNode* rtType = rt_params[rtParamIndex].get!VariableDeclNode(c).type.get_node(c);
397 
398 			if (rtType.astType == AstType.expr_name_use)
399 			{
400 				auto typeName = rtType.as!NameUseExprNode(c);
401 				Identifier typeId = typeName.id(c);
402 				AstIndex symIndex = paramNames.get(typeId, AstIndex.init);
403 
404 				if (symIndex)
405 				{
406 					// we got template parameter
407 					auto ctParam = symIndex.get!TemplateParamDeclNode(c);
408 					assert(!ctParam.isVariadic);
409 					processTemplatedArg(argTypeIndex, ctParam);
410 				}
411 			}
412 		}
413 	}
414 
415 	// group 1
416 	foreach(size_t i, ref AstIndex arg; rt_args)
417 	{
418 		require_type_check(arg, state); // do not cache arg, because require_type_check may modify it
419 		AstIndex argTypeIndex = arg.get_expr_type(c);
420 		assert(i < numRtParams);
421 
422 		VariableDeclNode* rt_param = rt_params[i].get!VariableDeclNode(c);
423 		AstNode* rt_type = rt_param.type.get_node(c);
424 
425 		if (rt_type.astType == AstType.expr_name_use)
426 		{
427 			auto typeName = rt_type.as!NameUseExprNode(c);
428 			Identifier typeId = typeName.id(c);
429 			AstIndex symIndex = paramNames.get(typeId, AstIndex.init);
430 			if (symIndex)
431 			{
432 				// we got template parameter
433 				auto ctParam = symIndex.get!TemplateParamDeclNode(c);
434 
435 				if (ctParam.isVariadic) {
436 					if (!rt_param.isVariadicParam) {
437 						reportCorrectExpandedParam(rt_param.loc, rt_param.id);
438 						c.unrecoverable_error(rt_param.loc, "Cannot expand non-variadic template parameter %s", c.idString(typeId));
439 					}
440 					// this and the rest of runtime args are going into CT variadic param
441 					processVariadicRtArgs(i);
442 					break;
443 				}
444 
445 				if (rt_param.isVariadicParam) {
446 					reportCorrectExpandedParam(rt_param.loc, rt_param.id);
447 					c.unrecoverable_error(rt_param.loc, "Cannot expand non-variadic template parameter %s", c.idString(typeId));
448 				}
449 
450 				processTemplatedArg(argTypeIndex, ctParam);
451 			}
452 			else if (rt_param.isVariadicParam)
453 			{
454 				reportCorrectExpandedParam(rt_param.loc, rt_param.id);
455 				c.unrecoverable_error(rt_param.loc, "Cannot expand parameter, type name is not found among template parameters");
456 			}
457 		}
458 		else if (rt_param.isVariadicParam)
459 		{
460 			reportCorrectExpandedParam(rt_param.loc, rt_param.id);
461 			c.unrecoverable_error(rt_param.loc, "Cannot expand parameter");
462 		}
463 	}
464 
465 	// check that all parameters before variadic were inferred
466 	foreach(uint i; 0..templ.numParamsBeforeVariadic) {
467 		AstIndex param = inferredTemplArgs[i];
468 		if (param.isDefined) continue;
469 
470 		auto ctParam = ct_params[i].get!TemplateParamDeclNode(c);
471 		c.error(loc, "Cannot infer template parameter %s", c.idString(ctParam.id));
472 		success = false;
473 	}
474 
475 	return inferredTemplArgs;
476 }
477 
478 void type_check_func_call(CallExprNode* node, FunctionSignatureNode* signature, Identifier funcId, ref TypeCheckState state)
479 {
480 	CompilationContext* c = state.context;
481 
482 	AstIndex signatureIndex = c.getAstNodeIndex(signature);
483 	require_type_check(signatureIndex, state, IsNested.no);
484 	node.type = signature.returnType;
485 
486 	AstNodes params = signature.parameters;
487 	auto numParams = params.length;
488 	auto numDefaultArgs = signature.numDefaultArgs;
489 	c.assertf(numParams >= numDefaultArgs, node.loc,
490 		"numParams(%s) < numDefaultArgs(%s)", numParams, numDefaultArgs);
491 	auto numRequiredArgs = numParams - numDefaultArgs;
492 	auto numArgs = node.args.length;
493 
494 	if (numArgs < numRequiredArgs) {
495 		if (numDefaultArgs == 0)
496 			c.error(node.loc, "Too few arguments to `%s`, got %s, expected %s",
497 				c.idString(funcId), numArgs, numParams);
498 		else
499 			c.error(node.loc, "Too few arguments to `%s`, got %s, expected %s-%s",
500 				c.idString(funcId), numArgs, numRequiredArgs, numParams);
501 		return;
502 	}
503 	else if (numArgs > numParams) {
504 		if (numDefaultArgs == 0)
505 			c.error(node.loc, "Too many arguments to `%s`, got %s, expected %s",
506 				c.idString(funcId), numArgs, numParams);
507 		else
508 			c.error(node.loc, "Too many arguments to `%s`, got %s, expected %s-%s",
509 				c.idString(funcId), numArgs, numRequiredArgs, numParams);
510 
511 		return;
512 	}
513 
514 	// We need to allocate for each call, because calls can be nested
515 	// We allocate here instead of in IR gen, because eval cannot happen at IR gen,
516 	// and we need to call gen_init_value_var for default args, which may need to eval
517 	node.argsValues = c.allocateTempArray!IrIndex(numParams + 1); // first argument is callee
518 
519 	// For named arguments
520 	Scope* parameterScope;
521 	if (node.hasNamedArgs && numParams > 0) {
522 		parameterScope = params[0].get!VariableDeclNode(c).parentScope.get_scope(c);
523 	}
524 
525 	uint parameterIndex = 0;
526 	bool skipPositionalArgs = false;
527 
528 	// check arguments
529 	// default arguments do not require checking here
530 	foreach (i, ref AstIndex arg; node.args)
531 	{
532 		require_type_check(arg, state);
533 
534 		AstNode* argNode = arg.get_node(c);
535 
536 		if (argNode.astType == AstType.expr_named_argument)
537 		{
538 			NamedArgumenExprNode* namedArg = argNode.as!NamedArgumenExprNode(c);
539 			Identifier argId = namedArg.getId(c);
540 			AstIndex paramIndex = parameterScope.symbols.get(argId, AstIndex.init);
541 			if (paramIndex.isUndefined) {
542 				c.error(namedArg.loc, "Function `%s` has no parameter named `%s`", c.idString(funcId), c.idString(argId));
543 				// we don't know the index of the next parameter, so we cannot tell which parameter is missing
544 				skipPositionalArgs = true;
545 				continue;
546 			}
547 			// restore reporting after we found a correct named parameters, since we know indicies after it
548 			skipPositionalArgs = false;
549 			VariableDeclNode* param = c.getAst!VariableDeclNode(paramIndex);
550 			// remember the index for IR generation
551 			namedArg.resolve(param.scopeIndex, c);
552 			parameterIndex = param.scopeIndex;
553 
554 			bool success = autoconvTo(namedArg.expr, param.type, c);
555 			if (!success)
556 				c.error(namedArg.expr.loc(c),
557 					"Named argument %s, must have type %s, not %s", c.idString(argId),
558 					param.type.printer(c),
559 					namedArg.expr.get_expr_type(c).printer(c));
560 			if (node.argsValues[parameterIndex+1] == IrIndex(1, IrValueKind.none)) {
561 				c.error(namedArg.loc, "Parameter `%s` provided several times", c.idString(argId));
562 			}
563 			node.argsValues[parameterIndex+1] = IrIndex(1, IrValueKind.none); // mark argument as set
564 		}
565 		else
566 		{
567 			if (skipPositionalArgs) continue;
568 
569 			if (parameterIndex >= numParams) {
570 				c.error(arg.loc(c), "Trying to provide parameter %s, while `%s` has %s parameters", parameterIndex+1, c.idString(funcId), numParams);
571 				++parameterIndex;
572 				continue;
573 			}
574 			VariableDeclNode* param = c.getAst!VariableDeclNode(params[parameterIndex]);
575 
576 			bool success = autoconvTo(arg, param.type, c);
577 			if (!success)
578 				c.error(arg.loc(c),
579 					"Argument %s, must have type %s, not %s", parameterIndex+1,
580 					param.type.printer(c),
581 					arg.get_expr_type(c).printer(c));
582 			if (node.argsValues[parameterIndex+1] == IrIndex(1, IrValueKind.none)) {
583 				c.error(argNode.loc, "Parameter `%s` was provided several times", c.idString(param.id));
584 			}
585 			node.argsValues[parameterIndex+1] = IrIndex(1, IrValueKind.none); // mark argument as set
586 		}
587 		++parameterIndex;
588 	}
589 
590 	foreach(i; 0..numParams)
591 	{
592 		// eval default argument values
593 		VariableDeclNode* param = c.getAst!VariableDeclNode(params[i]);
594 		if (node.argsValues[i+1].isDefined) continue;
595 		if (param.initializer.isUndefined) {
596 			if (param.isAnonymous)
597 				c.error(node.loc, "Missing argument for anonymous parameter %s", i+1);
598 			else
599 				c.error(node.loc, "Missing argument for parameter %s: `%s`", i+1, c.idString(param.id));
600 			continue;
601 		}
602 
603 		AstNode* initializer = param.initializer.get_node(c);
604 		if (initializer.astType == AstType.literal_special) {
605 			node.argsValues[i+1] = eval_literal_special(cast(SpecialKeyword)initializer.subType, node.loc, node.parentScope, c);
606 		} else {
607 			node.argsValues[i+1] = param.gen_init_value_var(c);
608 		}
609 	}
610 }
611 
612 void type_check_constructor_call(CallExprNode* node, StructDeclNode* s, ref TypeCheckState state)
613 {
614 	CompilationContext* c = state.context;
615 
616 	IrIndex structType = s.gen_ir_type_struct(c);
617 	uint numStructMembers = c.types.get!IrTypeStruct(structType).numMembers;
618 	node.argsValues = c.allocateTempArray!IrIndex(numStructMembers);
619 
620 	if (s.isUnion) {
621 		if (node.args.length > 1)
622 			c.error(node.loc, "union constructor must have a single argument, not %s", node.args.length);
623 	} else if (node.args.length > numStructMembers) {
624 		c.error(node.loc, "cannot initialize struct `%s` with %s arguments, it has %s members",
625 			c.idString(s.id), node.args.length, numStructMembers);
626 	}
627 
628 	void checkArgument(VariableDeclNode* memberVar, ref AstIndex arg)
629 	{
630 		AstIndex memberType = memberVar.type;
631 		bool success = autoconvTo(arg, memberType, c);
632 		if (!success) {
633 			c.error(arg.loc(c),
634 				"argument for member `%s`, must have type %s, not %s", c.idString(memberVar.id),
635 				memberType.printer(c),
636 				arg.get_expr_type(c).printer(c));
637 		}
638 	}
639 
640 	uint memberIndex;
641 	bool reportedMixed;
642 
643 	// We expect args to be either all positional or all named
644 	if (node.hasNamedArgs)
645 	{
646 		foreach (i, ref AstIndex arg; node.args)
647 		{
648 			require_type_check(arg, state);
649 
650 			AstNode* argNode = arg.get_node(c);
651 
652 			if (argNode.astType != AstType.expr_named_argument) {
653 				if (!reportedMixed)
654 					c.error(argNode.loc, "named and positional arguments cannot be mixed in struct constructor");
655 				reportedMixed = true;
656 				continue;
657 			}
658 
659 			NamedArgumenExprNode* namedArg = argNode.as!NamedArgumenExprNode(c);
660 			Identifier argId = namedArg.getId(c);
661 
662 			AstIndex memberNodeIndex = s.memberScope.lookup_scope(argId, c);
663 			if (memberNodeIndex.isUndefined) {
664 				c.error(namedArg.loc, "%s `%s` has no member named `%s`", s.structOrUnionString, c.idString(s.id), c.idString(argId));
665 				continue;
666 			}
667 
668 			if (!isDynamicStructMember(memberNodeIndex, c)) {
669 				c.error(namedArg.loc, "cannot initialize %s `%s` of %s `%s`", get_node_kind_name(memberNodeIndex, c), c.idString(argId), s.structOrUnionString, c.idString(s.id));
670 				continue;
671 			}
672 
673 			VariableDeclNode* memberVar = memberNodeIndex.get!VariableDeclNode(c);
674 			namedArg.resolve(memberVar.scopeIndex, c);
675 			checkArgument(memberVar, namedArg.expr);
676 		}
677 	}
678 	else
679 	{
680 		foreach(uint i, AstIndex member; StructDynMemberIterator(s, c))
681 		{
682 			if (node.args.length == memberIndex) break;
683 
684 			VariableDeclNode* memberVar = member.get!VariableDeclNode(c);
685 			require_type_check(node.args[memberIndex], state);
686 
687 			checkArgument(memberVar, node.args[memberIndex]);
688 			++memberIndex;
689 		}
690 	}
691 
692 	// will iterate the rest of members when positional or all members when named
693 	foreach(ref AstIndex member; s.declarations[memberIndex..$])
694 	{
695 		if (!isDynamicStructMember(member, c)) continue;
696 		VariableDeclNode* memberVar = member.get!VariableDeclNode(c);
697 		// init with initializer from struct definition
698 		node.argsValues[memberIndex] = memberVar.gen_init_value_var(c);
699 		++memberIndex;
700 	}
701 
702 	node.type = c.getAstNodeIndex(s);
703 }
704 
705 ExprValue ir_gen_call(ref IrGenState gen, IrIndex currentBlock, ref IrLabel nextStmt, CallExprNode* node)
706 {
707 	CompilationContext* c = gen.context;
708 
709 	AstIndex callee = node.callee.get_effective_node(c);
710 
711 	switch (callee.astType(c))
712 	{
713 		case AstType.decl_function:
714 			auto func = callee.get!FunctionDeclNode(c);
715 			IrIndex irIndex = func.getIrIndex(c);
716 			return visitCall(gen, func.signature, irIndex, currentBlock, nextStmt, node);
717 		case AstType.decl_struct:
718 			return visitConstructor(gen, callee.get!StructDeclNode(c), currentBlock, nextStmt, node);
719 		case AstType.decl_enum_member:
720 			// TODO: clean up
721 			TypeNode* varType = callee.get_node_type(c).get_type(c);
722 			if (!varType.isPointer) goto default;
723 			TypeNode* base = varType.as_ptr.base.get_type(c);
724 			if (!base.isFuncSignature) goto default;
725 			IrIndex irIndex = callee.get!EnumMemberDecl(c).gen_init_value_enum_member(c);
726 			return visitCall(gen, c.getAstNodeIndex(base), irIndex, currentBlock, nextStmt, node);
727 		case AstType.decl_var:
728 			VariableDeclNode* var = callee.get!VariableDeclNode(c);
729 			TypeNode* varType = var.type.get_type(c);
730 			if (!varType.isPointer) goto default;
731 			TypeNode* base = varType.as_ptr.base.get_type(c);
732 			if (!base.isFuncSignature) goto default;
733 
734 			IrIndex irIndex = var.irValue.rvalue(gen, node.loc, currentBlock);
735 			return visitCall(gen, c.getAstNodeIndex(base), irIndex, currentBlock, nextStmt, node);
736 		case AstType.expr_member:
737 			// Can probably fold other cases into this one
738 			TypeNode* exprType = callee.get_expr_type(c).get_type(c);
739 			if (!exprType.isPointer) goto default;
740 			TypeNode* base = exprType.as_ptr.base.get_type(c);
741 			if (!base.isFuncSignature) goto default;
742 
743 			IrLabel afterCallee = IrLabel(currentBlock);
744 			ExprValue calleeLval = ir_gen_expr(gen, callee, currentBlock, afterCallee);
745 			currentBlock = afterCallee.blockIndex;
746 			IrIndex calleeRval = calleeLval.rvalue(gen, node.loc, currentBlock);
747 
748 			return visitCall(gen, c.getAstNodeIndex(base), calleeRval, currentBlock, nextStmt, node);
749 		default:
750 			c.internal_error(node.loc, "Cannot call %s", callee.get_node_type(c).get_type(c).printer(c));
751 	}
752 }
753 
754 ExprValue visitCall(ref IrGenState gen, AstIndex signatureIndex, IrIndex callee, IrIndex currentBlock, ref IrLabel nextStmt, CallExprNode* n)
755 {
756 	CompilationContext* c = gen.context;
757 	auto signature = signatureIndex.get!FunctionSignatureNode(c);
758 	uint numArgs = n.args.length;
759 	uint numParams = signature.parameters.length;
760 	c.assertf(callee.isDefined, n.loc, "Undefined callee");
761 	c.assertf(numArgs+1 <= IrInstrHeader.MAX_ARGS, n.loc,
762 		"Cannot generate a call with %s arguments, max args is %s",
763 		numArgs, IrInstrHeader.MAX_ARGS-1);
764 
765 	n.argsValues[0] = callee;
766 	bool alwaysInline;
767 
768 	if (callee.kind == IrValueKind.func)
769 	{
770 		// force creation of function type for external functions
771 		gen_ir_type(signatureIndex, c);
772 		FunctionDeclNode* calleeFunc = c.getFunction(callee);
773 		alwaysInline = calleeFunc.isInline;
774 	}
775 
776 	uint parameterIndex = 0;
777 
778 	foreach (i, AstIndex arg; n.args)
779 	{
780 		AstNode* argNode = arg.get_node(c);
781 		if (argNode.astType == AstType.expr_named_argument)
782 		{
783 			NamedArgumenExprNode* namedArg = argNode.as!NamedArgumenExprNode(c);
784 			arg = namedArg.expr;
785 			parameterIndex = namedArg.getParamIndex(c);
786 			IrLabel afterArg = IrLabel(currentBlock);
787 			ExprValue lval = ir_gen_expr(gen, namedArg.expr, currentBlock, afterArg);
788 			currentBlock = afterArg.blockIndex;
789 			n.argsValues[parameterIndex+1] = lval.rvalue(gen, n.loc, currentBlock); // account for callee in 0th index
790 		}
791 		else
792 		{
793 			IrLabel afterArg = IrLabel(currentBlock);
794 			ExprValue lval = ir_gen_expr(gen, arg, currentBlock, afterArg);
795 			currentBlock = afterArg.blockIndex;
796 			n.argsValues[parameterIndex+1] = lval.rvalue(gen, n.loc, currentBlock); // account for callee in 0th index
797 		}
798 		debug c.assertf(n.argsValues[parameterIndex+1].isDefined, "Arg %s %s (%s) is undefined", parameterIndex+1, n.astType, c.tokenLoc(n.loc));
799 		++parameterIndex;
800 	}
801 
802 	// default args are populated in type check
803 
804 	// TODO: support more than plain func() calls. Such as func_array[42](), (*func_ptr)() etc
805 	// need handling of function pointers
806 
807 	if (signature.returnType.isVoidType(c))
808 	{
809 		InstrWithResult res = gen.builder.emitInstr!(IrOpcode.call)(currentBlock, n.argsValues);
810 		gen.builder.ir.getInstr(res.instruction).alwaysInline = alwaysInline;
811 		c.assertf(!res.result.isDefined, "Call has result");
812 		gen.builder.addJumpToLabel(currentBlock, nextStmt);
813 		return ExprValue();
814 	}
815 	else if (signature.returnType.isNoreturnType(c))
816 	{
817 		InstrWithResult res = gen.builder.emitInstr!(IrOpcode.call)(currentBlock, n.argsValues);
818 		gen.builder.addUnreachable(currentBlock);
819 		gen.builder.ir.getInstr(res.instruction).alwaysInline = alwaysInline;
820 		c.assertf(!res.result.isDefined, "Call has result");
821 		return ExprValue();
822 	}
823 	else
824 	{
825 		IrIndex callResultType = signature.returnType.gen_ir_type(c);
826 
827 		ExtraInstrArgs extra = { hasResult : true, type : callResultType };
828 		InstrWithResult res = gen.builder.emitInstr!(IrOpcode.call)(currentBlock, extra, n.argsValues);
829 		gen.builder.ir.getInstr(res.instruction).alwaysInline = alwaysInline;
830 		gen.builder.addJumpToLabel(currentBlock, nextStmt);
831 		return ExprValue(res.result);
832 	}
833 }
834 
835 ExprValue visitConstructor(ref IrGenState gen, StructDeclNode* s, IrIndex currentBlock, ref IrLabel nextStmt, CallExprNode* node)
836 {
837 	CompilationContext* c = gen.context;
838 
839 	uint numArgs = node.args.length;
840 	uint numMembers = cast(uint)node.argsValues.length;
841 
842 	if (numArgs == 0)
843 	{
844 		return ExprValue(s.gen_init_value_struct(c));
845 	}
846 
847 	bool allConstants = true;
848 	bool allZeroes = true;
849 
850 	if (node.hasNamedArgs)
851 	{
852 		foreach (i, ref AstIndex arg; node.args)
853 		{
854 			NamedArgumenExprNode* namedArg = arg.get!NamedArgumenExprNode(c);
855 
856 			IrLabel afterArg = IrLabel(currentBlock);
857 			ExprValue lval = ir_gen_expr(gen, namedArg.expr, currentBlock, afterArg);
858 			currentBlock = afterArg.blockIndex;
859 			IrIndex memberValue = lval.rvalue(gen, node.loc, currentBlock);
860 
861 			if (memberValue.isVirtReg) allConstants = false;
862 			if (!memberValue.isConstantZero) allZeroes = false;
863 			node.argsValues[namedArg.getParamIndex(c)] = memberValue;
864 		}
865 	}
866 	else
867 	{
868 		uint memberIndex;
869 		foreach(AstIndex member; s.declarations)
870 		{
871 			if (!isDynamicStructMember(member, c)) continue;
872 			if (numArgs == memberIndex) break; // no more positional args provided, others are default inited
873 
874 			IrLabel afterArg = IrLabel(currentBlock);
875 			ExprValue lval = ir_gen_expr(gen, node.args[memberIndex], currentBlock, afterArg);
876 			currentBlock = afterArg.blockIndex;
877 			IrIndex memberValue = lval.rvalue(gen, node.loc, currentBlock);
878 
879 			if (memberValue.isVirtReg) allConstants = false;
880 			if (!memberValue.isConstantZero) allZeroes = false;
881 			node.argsValues[memberIndex] = memberValue;
882 
883 			++memberIndex;
884 		}
885 	}
886 
887 	// check the rest of args for all zeroes
888 	if (allConstants)
889 	foreach (uint i; numArgs..numMembers) {
890 		if (!node.argsValues[i].isConstantZero) {
891 			allZeroes = false;
892 			break;
893 		}
894 	}
895 
896 	if (node.isLvalue) {
897 		c.internal_error(node.loc, "Constructor cannot be an l-value");
898 	}
899 	assert(s.irType.isDefined);
900 
901 	if (allZeroes)
902 	{
903 		return ExprValue(c.constants.addZeroConstant(s.irType));
904 	}
905 	else if (allConstants)
906 	{
907 		return ExprValue(c.constants.addAggrecateConstant(s.irType, node.argsValues));
908 	}
909 	else
910 	{
911 		ExtraInstrArgs extra = { type : s.irType };
912 		InstrWithResult res = gen.builder.emitInstr!(IrOpcode.create_aggregate)(currentBlock, extra, node.argsValues);
913 		return ExprValue(res.result);
914 	}
915 }