Index: trunk/nv/lua/lua_function.hh
===================================================================
--- trunk/nv/lua/lua_function.hh	(revision 184)
+++ trunk/nv/lua/lua_function.hh	(revision 185)
@@ -92,5 +92,5 @@
  		inline void function<void>::call_result<void>( int params )
  		{
- 			call( params, 1 );
+ 			call( params, 0 );
  		}
 
Index: trunk/nv/lua/lua_state.hh
===================================================================
--- trunk/nv/lua/lua_state.hh	(revision 184)
+++ trunk/nv/lua/lua_state.hh	(revision 185)
@@ -4,4 +4,6 @@
 // This file is part of NV Libraries.
 // For conditions of distribution and use, see copyright notice in nv.hh
+//
+// TODO: the call() templates are copied over in table/state - can we get around that?
 
 #ifndef NV_LUA_HH
@@ -13,4 +15,5 @@
 #include <nv/flags.hh>
 #include <nv/lua/lua_path.hh>
+#include <nv/lua/lua_values.hh>
 #include <string>
 
@@ -52,4 +55,20 @@
 			bool get_boolean( const std::string& element, bool defval = false );
 
+			template< typename R, typename T >
+			R get( const T& key )
+			{
+				detail::push_value( L->L, key );
+				call_get();
+				return detail::pop_return_value( L->L )
+			}
+
+			template< typename R, typename T >
+			R raw_get( const T& key )
+			{
+				detail::push_value( L->L, key );
+				call_get_raw();
+				return detail::pop_return_value( L->L )
+			}
+
 			template< uint32 SIZE, typename T >
 			flags< SIZE, T > get_flags( const std::string& element )
@@ -65,5 +84,75 @@
 				get_raw_flags( element, flags.data(), flags.size() );
 			}
-		private:
+
+			template < typename R >
+			R call( const path& p )
+			{
+				if ( L->push_function( p, false ) )
+				{
+					if ( call_function( 0, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1 >
+			R call( const path& p, const T1& p1 )
+			{
+				if ( L->push_function( p, false ) )
+				{
+					detail::push_value( L, p1 );
+					if ( L->call_function( 1, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2 >
+			R call( const path& p, const T1& p1, const T2& p2 )
+			{
+				if ( L->push_function( p, false ) )
+				{
+					detail::push_values( L, p1, p2 );
+					if ( L->call_function( 2, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2, typename T3 >
+			R call( const path& p, const T1& p1, const T2& p2, const T3& p3 )
+			{
+				if ( L->push_function( p, false ) )
+				{
+					detail::push_values( L, p1, p2, p3 );
+					if ( L->call_function( 3, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2, typename T3, typename T4 >
+			R call( const path& p, const T1& p1, const T2& p2, const T3& p3, const T4& p4 )
+			{
+				if ( L->push_function( p, false ) )
+				{
+					detail::push_value( L, p1, p2, p3, p4 );
+					if ( L->call_function( 4, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+
+		private:
+			bool push_function( const path& p );
+			int call_function( int nargs, int nresults );
+			void call_get();
+			void call_get_raw();
 			void get_raw_flags( const std::string& element, uint8* data, uint32 count );
 
@@ -90,5 +179,73 @@
 			operator lua_State*() { return L; }
 			~state();
-		private:
+
+			template < typename R >
+			R call( const path& p )
+			{
+				if ( push_function( p ) )
+				{
+					if ( call_function( 0, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1 >
+			R call( const path& p, const T1& p1 )
+			{
+				if ( push_function( p ) )
+				{
+					detail::push_value( L, p1 );
+					if ( call_function( 1, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2 >
+			R call( const path& p, const T1& p1, const T2& p2 )
+			{
+				if ( push_function( p ) )
+				{
+					detail::push_values( L, p1, p2 );
+					if ( call_function( 2, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2, typename T3 >
+			R call( const path& p, const T1& p1, const T2& p2, const T3& p3 )
+			{
+				if ( push_function( p ) )
+				{
+					detail::push_values( L, p1, p2, p3 );
+					if ( call_function( 3, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+			template < typename R, typename T1, typename T2, typename T3, typename T4 >
+			R call( const path& p, const T1& p1, const T2& p2, const T3& p3, const T4& p4 )
+			{
+				if ( push_function( p ) )
+				{
+					detail::push_value( L, p1, p2, p3, p4 );
+					if ( call_function( 4, detail::return_count< R >::value ) == 0 )
+					{
+						return detail::pop_return_value<R>( L );
+					}
+				}
+				return R();
+			}
+
+		private:
+			bool push_function( const path& p, bool global = true );
+			int call_function( int nargs, int nresults );
 			int load_string( const std::string& code, const std::string& name );
 			int load_stream( std::istream& stream, const std::string& name );
Index: trunk/nv/lua/lua_values.hh
===================================================================
--- trunk/nv/lua/lua_values.hh	(revision 184)
+++ trunk/nv/lua/lua_values.hh	(revision 185)
@@ -76,8 +76,32 @@
 			void pop_value( lua_State *L, void*& p );
 			template < typename T >
-			void pop_value( lua_State *L, T& p )
+			inline void pop_value( lua_State *L, T& p )
 			{
 				pass_traits<T>::pop( L, p );
 			}
+			template < typename T >
+			inline T pop_return_value( lua_State *L )
+			{
+				T ret;
+				pass_traits<T>::pop( L, ret );
+				return ret;
+			}
+
+			template <>
+			inline void pop_return_value<void>( lua_State* )
+			{
+			}
+
+			template < typename T >
+			struct return_count
+			{
+				const static int value = 1;
+			};
+
+			template <>
+			struct return_count<void>
+			{
+				const static int value = 0;
+			};
 		}
 
Index: trunk/src/lua/lua_state.cc
===================================================================
--- trunk/src/lua/lua_state.cc	(revision 184)
+++ trunk/src/lua/lua_state.cc	(revision 185)
@@ -264,4 +264,15 @@
 }
 
+void lua::table_guard::call_get()
+{
+	lua_gettable( L->L, -2 );
+}
+
+void lua::table_guard::call_get_raw()
+{
+	lua_rawget( L->L, -2 );
+}
+
+
 void lua::table_guard::get_raw_flags( const std::string& element, uint8* data, uint32 count )
 {
@@ -375,2 +386,32 @@
 	}
 }
+
+int lua::state::call_function( int nargs, int nresults )
+{
+	int status = lua_pcall( L, nargs, nresults, 0 );
+	if ( status != 0 )
+	{
+		std::string error = lua_tostring( L, -1 );
+		lua_pop( L, 1 );
+		NV_LOG( LOG_ERROR, "Lua error : " << error )
+	}
+	return status;
+}
+
+bool lua::state::push_function( const path& p, bool global )
+{
+	if ( !p.resolve( L, global ) )
+	{
+		lua_pop( L, 1 );
+		NV_LOG( LOG_ERROR, "Lua error : not a valid path - " + p.to_string() );
+		return false;
+	}
+
+	if ( !lua_isfunction( L, -1 ) ) 
+	{
+		lua_pop( L, 1 );
+		NV_LOG( LOG_ERROR, "Lua error : not a valid function - " + p.to_string() );
+		return false;
+	}
+	return true;
+}
