private static bool TryCompileCall(FunctionCallSyntax call, CompiledMethod method, BasicBlockBuilder builder, IDiagnosticSink diagnostics, INameResolver nameResolver, out Temporary value) { value = default; // Get the callee var matchingMethods = nameResolver.ResolveMethod(call.Function.Name); if (matchingMethods.Count == 0) { diagnostics.Add(DiagnosticCode.MethodNotFound, call.Function.Position, call.Function.Name); return(false); } else if (matchingMethods.Count > 1) { // TODO: Test this case throw new NotImplementedException("Multiple matching methods"); } var declaration = matchingMethods[0]; // Assert that there is the right number of parameters if (call.Parameters.Count != declaration.ParameterTypes.Count) { diagnostics.Add(DiagnosticCode.ParameterCountMismatch, call.Position, actual: call.Parameters.Count.ToString(), expected: declaration.ParameterTypes.Count.ToString()); return(false); } // Evaluate the parameters, verifying their types var parameterIndices = new int[declaration.ParameterTypes.Count]; for (var i = 0; i < parameterIndices.Length; i++) { var paramIndex = TryCompileExpression(call.Parameters[i], declaration.ParameterTypes[i], method, builder, nameResolver, diagnostics); // If the compilation of the expression failed for some reason, the diagnostic is already logged if (paramIndex == -1) { return(false); } parameterIndices[i] = paramIndex; } // Emit a call operation var callType = declaration is ImportedMethodDeclaration ? MethodCallType.Imported : MethodCallType.Native; var callInfoIndex = method.AddCallInfo(declaration.BodyIndex, parameterIndices, declaration.FullName, callType); var resultIndex = method.AddLocal(declaration.ReturnType, LocalFlags.None); builder.AppendInstruction(Opcode.Call, callInfoIndex, 0, resultIndex); value = Temporary.FromLocal(declaration.ReturnType, resultIndex); return(true); }