function generateProgram(gl, program) {
    var glVertShader = compileShader(gl, gl.VERTEX_SHADER, program.vertexSrc);
    var glFragShader = compileShader(gl, gl.FRAGMENT_SHADER, program.fragmentSrc);
    var webGLProgram = gl.createProgram();
    gl.attachShader(webGLProgram, glVertShader);
    gl.attachShader(webGLProgram, glFragShader);
    gl.linkProgram(webGLProgram);
    if (!gl.getProgramParameter(webGLProgram, gl.LINK_STATUS)) {
        logProgramError(gl, webGLProgram, glVertShader, glFragShader);
    }
    program.attributeData = getAttributeData(webGLProgram, gl);
    program.uniformData = getUniformData(webGLProgram, gl);
    // GLSL 1.00: bind attributes sorted by name in ascending order
    // GLSL 3.00: don't change the attribute locations that where chosen by the compiler
    //            or assigned by the layout specifier in the shader source code
    if (!(/^[ \t]*#[ \t]*version[ \t]+300[ \t]+es[ \t]*$/m).test(program.vertexSrc)) {
        var keys = Object.keys(program.attributeData);
        keys.sort(function (a, b) { return (a > b) ? 1 : -1; }); // eslint-disable-line no-confusing-arrow
        for (var i = 0; i < keys.length; i++) {
            program.attributeData[keys[i]].location = i;
            gl.bindAttribLocation(webGLProgram, i, keys[i]);
        }
        gl.linkProgram(webGLProgram);
    }
    gl.deleteShader(glVertShader);
    gl.deleteShader(glFragShader);
    var uniformData = {};
    for (var i in program.uniformData) {
        var data = program.uniformData[i];
        uniformData[i] = {
            location: gl.getUniformLocation(webGLProgram, i),
            value: defaultValue(data.type, data.size),
        };
    }
    var glProgram = new GLProgram(webGLProgram, uniformData);
    return glProgram;
}
generates a WebGL Program object from a high level Pixi Program.
@param gl - a rendering context on which to generate the program
@param program - the high level Pixi Program.