function createProgram(gl, shaders, opt_attribs, opt_locations, opt_errorCallback) {
  // This code is really convoluted, because it may or may not be async
  // Maybe it would be better to have a separate function
  var progOptions = getProgramOptions(opt_attribs, opt_locations, opt_errorCallback);
  var shaderSet = new Set(shaders);
  var program = createProgramNoCheck(gl, shaders, progOptions);
  function hasErrors(gl, program) {
    var errors = getProgramErrors(gl, program, progOptions.errorCallback);
    if (errors) {
      deleteProgramAndShaders(gl, program, shaderSet);
    }
    return errors;
  }
  if (progOptions.callback) {
    waitForProgramLinkCompletionAsync(gl, program).then(function () {
      var errors = hasErrors(gl, program);
      progOptions.callback(errors, errors ? undefined : program);
    });
    return undefined;
  }
  return hasErrors(gl, program) ? undefined : program;
}
Creates a program, attaches (and/or compiles) shaders, binds attrib locations, links the
program.

NOTE: There are 4 signatures for this function

    twgl.createProgram(gl, [vs, fs], options);
    twgl.createProgram(gl, [vs, fs], opt_errFunc);
    twgl.createProgram(gl, [vs, fs], opt_attribs, opt_errFunc);
    twgl.createProgram(gl, [vs, fs], opt_attribs, opt_locations, opt_errFunc);

@param {WebGLRenderingContext} gl The WebGLRenderingContext to use.
@param {WebGLShader[]|string[]} shaders The shaders to attach, or element ids for their source, or strings that contain their source
@param {module:twgl.ProgramOptions|string[]|module:twgl.ErrorCallback} [opt_attribs] Options for the program or an array of attribs names or an error callback. Locations will be assigned by index if not passed in
@param {number[]|module:twgl.ErrorCallback} [opt_locations] The locations for the. A parallel array to opt_attribs letting you assign locations or an error callback.
@param {module:twgl.ErrorCallback} [opt_errorCallback] callback for errors. By default it just prints an error to the console
       on error. If you want something else pass an callback. It's passed an error message.
@return {WebGLProgram?} the created program or null if error of a callback was provided.
@memberOf module:twgl/programs