=== modified file 'program.cc'
--- program.cc	2011-06-09 20:36:25 +0000
+++ program.cc	2011-08-31 21:00:19 +0000
@@ -169,6 +169,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_);
@@ -252,101 +259,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
@@ -360,3 +283,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 'program.h'
--- program.h	2011-06-09 20:36:25 +0000
+++ program.h	2011-08-31 21:00:19 +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_;

