=== modified file 'src/libmatrix/program.cc'
--- src/libmatrix/program.cc	2011-08-10 17:55:38 +0000
+++ src/libmatrix/program.cc	2011-08-31 21:22:27 +0000
@@ -170,6 +170,13 @@
     // Clear out the error string to make sure we don't return anything stale.
     message_.clear();
 
+    // Release all of the symbol map resources.
+    for (std::map<string, Symbol*>::iterator symbolIt = symbols_.begin(); symbolIt != symbols_.end(); symbolIt++)
+    {
+        delete (*symbolIt).second;
+    }
+    symbols_.clear();
+
     if (handle_)
     {
         glDeleteProgram(handle_);
@@ -253,101 +260,17 @@
     glUseProgram(0);
 }
 
-void
-Program::loadUniformMatrix(const mat4& m, const string& name)
-{
-    ready_ = false;
-    GLint location = glGetUniformLocation(handle_, name.c_str());
-    if (location < 0)
-    {
-        message_ = string("Failed to get uniform location for \"") + name +
-            string("\"");
-        return;
-    }
-
-    // Our matrix representation is column-major, so transpose is false here.
-    glUniformMatrix4fv(location, 1, GL_FALSE, m);
-    ready_ = true;
-}
-
-void
-Program::loadUniformVector(const vec2& v, const string& name)
-{
-    ready_ = false;
-    GLint location = glGetUniformLocation(handle_, name.c_str());
-    if (location < 0)
-    {
-        message_ = string("Failed to get uniform location for \"") + name +
-            string("\"");
-        return;
-    }
-
-    glUniform2fv(location, 1, v);
-    ready_ = true;
-}
-
-void
-Program::loadUniformVector(const vec3& v, const string& name)
-{
-    ready_ = false;
-    GLint location = glGetUniformLocation(handle_, name.c_str());
-    if (location < 0)
-    {
-        message_ = string("Failed to get uniform location for \"") + name +
-            string("\"");
-        return;
-    }
-
-    glUniform3fv(location, 1, v);
-    ready_ = true;
-}
-
-void
-Program::loadUniformVector(const vec4& v, const string& name)
-{
-    ready_ = false;
-    GLint location = glGetUniformLocation(handle_, name.c_str());
-    if (location < 0)
-    {
-        message_ = string("Failed to get uniform location for \"") + name +
-            string("\"");
-        return;
-    }
-
-    glUniform4fv(location, 1, v);
-    ready_ = true;
-}
-
-void
-Program::loadUniformScalar(const float& f, const string& name)
-{
-    ready_ = false;
-    GLint location = glGetUniformLocation(handle_, name.c_str());
-    if (location < 0)
-    {
-        message_ = string("Failed to get uniform location for \"") + name +
-            string("\"");
-        return;
-    }
-
-    glUniform1f(location, f);
-    ready_ = true;
-}
-
-void
-Program::loadUniformScalar(const int& i, const string& name)
-{
-    ready_ = false;
-    GLint location = glGetUniformLocation(handle_, name.c_str());
-    if (location < 0)
-    {
-        message_ = string("Failed to get uniform location for \"") + name +
-            string("\"");
-        return;
-    }
-
-    glUniform1i(location, i);
-    ready_ = true;
+
+int
+Program::getUniformLocation(const string& name)
+{
+    GLint location = glGetUniformLocation(handle_, name.c_str());
+    if (location < 0)
+    {
+        message_ = string("Failed to get uniform location for \"") + name +
+            string("\"");
+    }
+    return location;
 }
 
 int
@@ -361,3 +284,87 @@
     }
     return index;
 }
+
+Program::Symbol&
+Program::Symbol::operator=(const mat4& m)
+{
+    if (type_ == Uniform)
+    {
+        // Our matrix representation is column-major, so transpose is false here.
+        glUniformMatrix4fv(location_, 1, GL_FALSE, m);
+    }
+    return *this;
+}
+
+Program::Symbol&
+Program::Symbol::operator=(const vec2& v)
+{
+    if (type_ == Uniform)
+    {
+        glUniform2fv(location_, 1, v);
+    }
+    return *this;
+}
+
+Program::Symbol&
+Program::Symbol::operator=(const vec3& v)
+{
+    if (type_ == Uniform)
+    {
+        glUniform3fv(location_, 1, v);
+    }
+    return *this;
+}
+
+Program::Symbol&
+Program::Symbol::operator=(const vec4& v)
+{
+    if (type_ == Uniform)
+    {
+        glUniform4fv(location_, 1, v);
+    }
+    return *this;
+}
+
+Program::Symbol&
+Program::Symbol::operator=(const float& f)
+{
+    if (type_ == Uniform)
+    {
+        glUniform1f(location_, f);
+    }
+    return *this;
+}
+
+Program::Symbol&
+Program::Symbol::operator=(const int& i)
+{
+    if (type_ == Uniform)
+    {
+        glUniform1i(location_, i);
+    }
+    return *this;
+}
+
+Program::Symbol&
+Program::operator[](const std::string& name)
+{
+    std::map<std::string, Symbol*>::iterator mapIt = symbols_.find(name);
+    if (mapIt == symbols_.end())
+    {
+        Program::Symbol::SymbolType type(Program::Symbol::Attribute);
+        int location = getAttribIndex(name);
+        if (location < 0)
+        {
+            // No attribute found by that name.  Let's try a uniform...
+            type = Program::Symbol::Uniform;
+            location = getUniformLocation(name);
+            if (location < 0)
+            {
+                type = Program::Symbol::None;
+            }
+        }
+        mapIt = symbols_.insert(mapIt, std::make_pair(name, new Symbol(name, location, type)));
+    }
+    return *(*mapIt).second;
+}

=== modified file 'src/libmatrix/program.h'
--- src/libmatrix/program.h	2011-06-17 07:54:50 +0000
+++ src/libmatrix/program.h	2011-08-31 21:22:27 +0000
@@ -14,6 +14,7 @@
 
 #include <string>
 #include <vector>
+#include <map>
 #include "mat.h"
 
 // Simple shader container.  Abstracts all of the OpenGL bits, but leaves
@@ -108,26 +109,38 @@
     // using it).
     void stop();
 
-    // These members cause data to be bound to program variables, so
-    // the program must be bound for use for these to be effective.
-    //
-    // Load a matrix into the named uniform variable in the program.
-    void loadUniformMatrix(const LibMatrix::mat4& m, const std::string& name);
-    // Load a vector into the named uniform variable in the program.
-    void loadUniformVector(const LibMatrix::vec2& v, const std::string& name);
-    // Load a vector into the named uniform variable in the program.
-    void loadUniformVector(const LibMatrix::vec3& v, const std::string& name);
-    // Load a vector into the named uniform variable in the program.
-    void loadUniformVector(const LibMatrix::vec4& v, const std::string& name);
-    // Load a scalar into the named uniform variable in the program.
-    void loadUniformScalar(const float& f, const std::string& name);
-    // Load a scalar into the named uniform variable in the program.
-    void loadUniformScalar(const int& i, const std::string& name);
-
+    class Symbol
+    {
+public:
+        enum SymbolType
+        {
+            None,
+            Attribute,
+            Uniform
+        };
+        Symbol(const std::string& name, int location, SymbolType type) :
+            type_(type),
+            location_(location),
+            name_(name) {}
+        int location() const { return location_; }
+        // These members cause data to be bound to program variables, so
+        // the program must be bound for use for these to be effective.
+        Symbol& operator=(const LibMatrix::mat4& m);
+        Symbol& operator=(const LibMatrix::vec2& v);
+        Symbol& operator=(const LibMatrix::vec3& v);
+        Symbol& operator=(const LibMatrix::vec4& v);
+        Symbol& operator=(const float& f);
+        Symbol& operator=(const int& i);
+private:
+        Symbol();
+        SymbolType type_;
+        GLint location_;
+        std::string name_;
+    };
     // Get the handle to a named program input (the location in OpenGL
     // vernacular).  Typically used in conjunction with various VertexAttrib
-    // interfaces.
-    int getAttribIndex(const std::string& name);
+    // interfaces.  Equality operators are used to load uniform data.
+    Symbol& operator[](const std::string& name);
 
     // If "valid" then the program has successfully been created.
     // If "ready" then the program has successfully been built.
@@ -138,7 +151,10 @@
     const std::string& errorMessage() const { return message_; }
 
 private:
+    int getAttribIndex(const std::string& name);
+    int getUniformLocation(const std::string& name);
     unsigned int handle_;
+    std::map<std::string, Symbol*> symbols_;
     std::vector<Shader> shaders_;
     std::string message_;
     bool ready_;

=== modified file 'src/scene-build.cpp'
--- src/scene-build.cpp	2011-07-28 08:44:31 +0000
+++ src/scene-build.cpp	2011-08-31 21:22:27 +0000
@@ -74,8 +74,8 @@
     }
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
-    attrib_locations.push_back(mProgram.getAttribIndex("normal"));
+    attrib_locations.push_back(mProgram["position"].location());
+    attrib_locations.push_back(mProgram["normal"].location());
     mMesh.set_attrib_locations(attrib_locations);
 
     mRotationSpeed = 36.0f;
@@ -157,13 +157,13 @@
     model_view.rotate(mRotation, 0.0f, 1.0f, 0.0f);
     model_view_proj *= model_view.getCurrent();
 
-    mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
+    mProgram["ModelViewProjectionMatrix"] = model_view_proj;
 
     // Load the NormalMatrix uniform in the shader. The NormalMatrix is the
     // inverse transpose of the model view matrix.
     LibMatrix::mat4 normal_matrix(model_view.getCurrent());
     normal_matrix.inverse().transpose();
-    mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
+    mProgram["NormalMatrix"] = normal_matrix;
 
     if (mUseVbo) {
         mMesh.render_vbo();

=== modified file 'src/scene-bump.cpp'
--- src/scene-bump.cpp	2011-08-17 09:10:47 +0000
+++ src/scene-bump.cpp	2011-08-31 21:22:27 +0000
@@ -97,8 +97,8 @@
     }
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
-    attrib_locations.push_back(mProgram.getAttribIndex("normal"));
+    attrib_locations.push_back(mProgram["position"].location());
+    attrib_locations.push_back(mProgram["normal"].location());
     mMesh.set_attrib_locations(attrib_locations);
 }
 
@@ -144,8 +144,8 @@
     }
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
-    attrib_locations.push_back(mProgram.getAttribIndex("texcoord"));
+    attrib_locations.push_back(mProgram["position"].location());
+    attrib_locations.push_back(mProgram["texcoord"].location());
     mMesh.set_attrib_locations(attrib_locations);
 
     Texture::load(GLMARK_DATA_PATH"/textures/asteroid-normal-map.png", &mTexture,
@@ -169,7 +169,7 @@
     mProgram.start();
 
     // Load texture sampler value
-    mProgram.loadUniformScalar(0, "NormalMap");
+    mProgram["NormalMap"] = 0;
 
     mCurrentFrame = 0;
     mRotation = 0.0;
@@ -221,13 +221,13 @@
     model_view.rotate(mRotation, 0.0f, 1.0f, 0.0f);
     model_view_proj *= model_view.getCurrent();
 
-    mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
+    mProgram["ModelViewProjectionMatrix"] = model_view_proj;
 
     // Load the NormalMatrix uniform in the shader. The NormalMatrix is the
     // inverse transpose of the model view matrix.
     LibMatrix::mat4 normal_matrix(model_view.getCurrent());
     normal_matrix.inverse().transpose();
-    mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
+    mProgram["NormalMatrix"] = normal_matrix;
 
     mMesh.render_vbo();
 }

=== modified file 'src/scene-conditionals.cpp'
--- src/scene-conditionals.cpp	2011-07-27 15:03:54 +0000
+++ src/scene-conditionals.cpp	2011-08-31 21:22:27 +0000
@@ -117,7 +117,7 @@
     mProgram.start();
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
+    attrib_locations.push_back(mProgram["position"].location());
     mMesh.set_attrib_locations(attrib_locations);
 
     mRunning = true;

=== modified file 'src/scene-effect-2d.cpp'
--- src/scene-effect-2d.cpp	2011-08-09 11:21:35 +0000
+++ src/scene-effect-2d.cpp	2011-08-31 21:22:27 +0000
@@ -336,13 +336,13 @@
     mesh_.build_vbo();
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(program_.getAttribIndex("position"));
+    attrib_locations.push_back(program_["position"].location());
     mesh_.set_attrib_locations(attrib_locations);
 
     program_.start();
 
     // Load texture sampler value
-    program_.loadUniformScalar(0, "Texture0");
+    program_["Texture0"] = 0;
 
     mCurrentFrame = 0;
     mRunning = true;

=== modified file 'src/scene-function.cpp'
--- src/scene-function.cpp	2011-07-27 15:03:54 +0000
+++ src/scene-function.cpp	2011-08-31 21:22:27 +0000
@@ -147,7 +147,7 @@
     mProgram.start();
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
+    attrib_locations.push_back(mProgram["position"].location());
     mMesh.set_attrib_locations(attrib_locations);
 
     mRunning = true;

=== modified file 'src/scene-grid.cpp'
--- src/scene-grid.cpp	2011-08-11 08:57:47 +0000
+++ src/scene-grid.cpp	2011-08-31 21:22:27 +0000
@@ -123,7 +123,7 @@
     model_view.rotate(mRotation, 0.0f, 0.0f, 1.0f);
     model_view_proj *= model_view.getCurrent();
 
-    mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
+    mProgram["ModelViewProjectionMatrix"] = model_view_proj;
 
     mMesh.render_vbo();
 }

=== modified file 'src/scene-loop.cpp'
--- src/scene-loop.cpp	2011-07-27 15:03:54 +0000
+++ src/scene-loop.cpp	2011-08-31 21:22:27 +0000
@@ -142,11 +142,11 @@
 
     mProgram.start();
 
-    mProgram.loadUniformScalar(vtx_steps, "VertexLoops");
-    mProgram.loadUniformScalar(frg_steps, "FragmentLoops");
+    mProgram["VertexLoops"] = vtx_steps;
+    mProgram["FragmentLoops"] = frg_steps;
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
+    attrib_locations.push_back(mProgram["position"].location());
     mMesh.set_attrib_locations(attrib_locations);
 
     mRunning = true;

=== modified file 'src/scene-pulsar.cpp'
--- src/scene-pulsar.cpp	2011-08-18 13:43:31 +0000
+++ src/scene-pulsar.cpp	2011-08-31 21:22:27 +0000
@@ -194,14 +194,14 @@
         model_view.rotate(mRotations[i].y(), 0.0f, 1.0f, 0.0f);
         model_view.rotate(mRotations[i].z(), 0.0f, 0.0f, 1.0f);
         model_view_proj *= model_view.getCurrent();
-        mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
+        mProgram["ModelViewProjectionMatrix"] = model_view_proj;
 
         if (mOptions["light"].value == "true") {
             // Load the NormalMatrix uniform in the shader. The NormalMatrix is the
             // inverse transpose of the model view matrix.
             LibMatrix::mat4 normal_matrix(model_view.getCurrent());
             normal_matrix.inverse().transpose();
-            mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
+            mProgram["NormalMatrix"] = normal_matrix;
         }
 
         mPlaneMesh.render_vbo();
@@ -283,12 +283,12 @@
 
     // Set attribute locations
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
-    attrib_locations.push_back(mProgram.getAttribIndex("vtxcolor"));
+    attrib_locations.push_back(mProgram["position"].location());
+    attrib_locations.push_back(mProgram["vtxcolor"].location());
     if (texture)
-        attrib_locations.push_back(mProgram.getAttribIndex("texcoord"));
+        attrib_locations.push_back(mProgram["texcoord"].location());
     if (light)
-        attrib_locations.push_back(mProgram.getAttribIndex("normal"));
+        attrib_locations.push_back(mProgram["normal"].location());
     mPlaneMesh.set_attrib_locations(attrib_locations);
 }
 

=== modified file 'src/scene-shading.cpp'
--- src/scene-shading.cpp	2011-07-28 08:44:31 +0000
+++ src/scene-shading.cpp	2011-08-31 21:22:27 +0000
@@ -121,8 +121,8 @@
     mProgram.start();
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
-    attrib_locations.push_back(mProgram.getAttribIndex("normal"));
+    attrib_locations.push_back(mProgram["position"].location());
+    attrib_locations.push_back(mProgram["normal"].location());
     mMesh.set_attrib_locations(attrib_locations);
 
     mCurrentFrame = 0;
@@ -168,16 +168,16 @@
     model_view.rotate(mRotation, 0.0f, 1.0f, 0.0f);
     model_view_proj *= model_view.getCurrent();
 
-    mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
+    mProgram["ModelViewProjectionMatrix"] = model_view_proj;
 
     // Load the NormalMatrix uniform in the shader. The NormalMatrix is the
     // inverse transpose of the model view matrix.
     LibMatrix::mat4 normal_matrix(model_view.getCurrent());
     normal_matrix.inverse().transpose();
-    mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
+    mProgram["NormalMatrix"] = normal_matrix;
 
     // Load the modelview matrix itself
-    mProgram.loadUniformMatrix(model_view.getCurrent(), "ModelViewMatrix");
+    mProgram["ModelViewMatrix"] = model_view.getCurrent();
 
     mMesh.render_vbo();
 }

=== modified file 'src/scene-texture.cpp'
--- src/scene-texture.cpp	2011-07-28 08:44:31 +0000
+++ src/scene-texture.cpp	2011-08-31 21:22:27 +0000
@@ -73,9 +73,9 @@
     }
 
     std::vector<GLint> attrib_locations;
-    attrib_locations.push_back(mProgram.getAttribIndex("position"));
-    attrib_locations.push_back(mProgram.getAttribIndex("normal"));
-    attrib_locations.push_back(mProgram.getAttribIndex("texcoord"));
+    attrib_locations.push_back(mProgram["position"].location());
+    attrib_locations.push_back(mProgram["normal"].location());
+    attrib_locations.push_back(mProgram["texcoord"].location());
     mCubeMesh.set_attrib_locations(attrib_locations);
 
     mRotationSpeed = LibMatrix::vec3(36.0f, 36.0f, 36.0f);
@@ -165,13 +165,13 @@
     model_view.rotate(mRotation.z(), 0.0f, 0.0f, 1.0f);
     model_view_proj *= model_view.getCurrent();
 
-    mProgram.loadUniformMatrix(model_view_proj, "ModelViewProjectionMatrix");
+    mProgram["ModelViewProjectionMatrix"] = model_view_proj;
 
     // Load the NormalMatrix uniform in the shader. The NormalMatrix is the
     // inverse transpose of the model view matrix.
     LibMatrix::mat4 normal_matrix(model_view.getCurrent());
     normal_matrix.inverse().transpose();
-    mProgram.loadUniformMatrix(normal_matrix, "NormalMatrix");
+    mProgram["NormalMatrix"] = normal_matrix;
 
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, mTexture);

