Index: trunk/nv/lua/lua_state.hh
===================================================================
--- trunk/nv/lua/lua_state.hh	(revision 181)
+++ 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 );
