Exemple #1
0
 /// <summary>[-0, +0, v] Raises an error. It adds at the beginning of the message the file name and the line number where the error occurred, if this information is available. This function never returns, but it is an idiom to use it in C functions as <c>return luaL.error(args)</c>.</summary>
 public static int error(lua.State L, string message)
 {
     // re-implemented to avoid headaches with native variable arguments and Lua's format strings
     // luaL_error doesn't check the stack internally and it uses more stack than we do; it relies on EXTRA_STACK space.
     lua.pushstring(L, luanet.where (L, 1) + message);
     return(lua.error(L));
 }
Exemple #2
0
        /// <summary>[-0, +0, -] Returns whether the currently executing code was called by Lua.</summary>
        public static bool infunction(lua.State L)
        {
            // this function should resolve to the same thing as "L->ci != L->base_ci" in internal lua code
            var ar = new lua.Debug();

            return(lua.getstack(L, 0, ref ar));            // returns unsuccessful if there is no stack
        }
Exemple #3
0
 /// <summary>[-0, +0, m] Grows the stack size to top + <paramref name="sz"/> elements, throwing a CLR exception if the stack cannot grow to that size.</summary>
 /// <param name="L"></param><param name="sz"></param><param name="mes">An additional text to go into the error message.</param>
 /// <exception cref="LuaScriptException"></exception>
 public static void checkstack(lua.State L, int sz, string mes)
 {
     Debug.Assert(!string.IsNullOrEmpty(mes));
     if (!lua.checkstack(L, sz))
     {
         throw new LuaScriptException(string.Format("stack overflow ({0})", mes), luanet.where (L, 1));
     }
 }
Exemple #4
0
        /// <summary>[-0, +1, m] Loads a buffer as a Lua chunk. This function uses <see cref="lua.load"/> to load the chunk in the string s, which can contain embedded zeros. <paramref name="name"/> is the chunk name, used for debug information and error messages.</summary>
        public static LUA.ERR loadbuffer(lua.State L, string s, string name)
        {
            Debug.Assert(s != null);
            IntPtr ptr = Marshal.StringToHGlobalAnsi(s);

            try { return(luaL.loadbuffer(L, ptr, s.Length, name)); }
            finally { Marshal.FreeHGlobal(ptr); }
        }
Exemple #5
0
        /// <summary>[-0, +0, -] Retrieves the object from a reference created by <see cref="newref"/>. The value at <paramref name="index"/> MUST be a reference created by <see cref="newref"/>; memory corruption or undefined behavior may result for any other value.<para>Returns null if the reference has been freed.</para><para>The *ref functions are thread-safe; they can used by Lua instances running on different threads.</para></summary>
        public static unsafe object getref(lua.State L, int index)
        {
            Debug.Assert(luaclr.isreflike(L, index));
            IntPtr *contents = (IntPtr *)lua.touserdata(L, index);
            var     handle   = *contents;

            return(handle == default(IntPtr) ? null : GCHandle.FromIntPtr(handle).Target);
        }
Exemple #6
0
 /// <summary>[-0, +0, v] Grows the stack size to top + <paramref name="sz"/> elements, raising an error if the stack cannot grow to that size.</summary>
 /// <param name="L"></param><param name="sz"></param><param name="mes">An additional text to go into the error message.</param>
 public static void checkstack(lua.State L, int sz, string mes)
 {
     // luaL_checkstack shouldn't be pinvoked. the message would be marshaled with each call but rarely used.
     Debug.Assert(!string.IsNullOrEmpty(mes));
     if (!lua.checkstack(L, sz))
     {
         luaL.error(L, "stack overflow ({0})", mes);
     }
 }
Exemple #7
0
        /// <summary>[-0, +0, -] Converts relative index to a normal (absolute) index. If the relative index goes out of the stack bounds, 0 is returned. If <paramref name="index"/> is not a relative index it is returned unchanged.</summary>
        public static int absoluteindex(lua.State L, int index)
        {
            if (index >= 0 || index <= LUA.REGISTRYINDEX)
            {
                return(index);
            }
            int i = lua.gettop(L) + index + 1;

            return(i < 0 ? 0 : i);
        }
Exemple #8
0
 public StackIndex(lua.State L, int index)
 {
     //Trace.TraceInformation("new StackIndex({0},{1})", L, index);
     L.NullCheck("L");
     if (index == 0)
     {
         throw new ArgumentOutOfRangeException("index");
     }
     this.L = L; this.Index = index;
 }
Exemple #9
0
        /// <summary><para>[-0, +0, v] Checks whether the function argument <paramref name="narg"/> is a struct instance of type <typeparamref name="T"/> and returns this object.</para></summary>
        public static T checkrefstruct <T>(lua.State L, int narg, string extramsg) where T : struct
        {
            var o = luaclr.checkref(L, narg);

            if (o is T == false)
            {
                luaL.argerror(L, narg, string.Format(extramsg ?? "{0} expected, got {1}", typeof(T).Name, o.GetType().FullName));
            }
            return((T)o);
        }
Exemple #10
0
 /// <summary>[-0, +1, e] Pushes a translation of the referenced object onto the stack.</summary>
 [MethodImpl(INLINE)] public static void pushobject <T>(lua.State L, T o) where T : IPushable        // Generic so structs don't need to be boxed.
 {
     if (o == null)
     {
         lua.pushnil(L);
     }
     else
     {
         o.push(L);
     }
 }
Exemple #11
0
        /// <summary>[-(nargs + 1), +(nresults|0), -]</summary>
        [MethodImpl(INLINE)] public static Exception pcall(lua.State L, int nargs, int nresults)
        {
            if (lua.pcall(L, nargs, nresults, 0) == LUA.ERR.Success)
            {
                return(null);
            }
            var message = lua.tostring(L, -1) ?? "Error message was a " + lua.type(L, -1).ToString();

            lua.pop(L, 1);
            return(new LuaScriptException(message, ""));            // todo
        }
Exemple #12
0
        /// <summary><para>[-0, +0, v] Checks whether the function argument <paramref name="narg"/> is a class instance of type <typeparamref name="T"/> and returns this object.</para></summary>
        public static T checkref <T>(lua.State L, int narg, string extramsg) where T : class
        {
            var o   = luaclr.checkref(L, narg);
            var ret = o as T;

            if (ret == null)
            {
                luaL.argerror(L, narg, string.Format(extramsg ?? "{0} expected, got {1}", typeof(T).Name, o.GetType().FullName));
            }
            return(ret);
        }
Exemple #13
0
 /// <summary>
 /// [-0, +1, e] Navigates fields nested in an object at the specified index, pushing the value of the specified sub-field. If <paramref name="fields"/> is empty it pushes a copy of the main object.
 /// <para>WARNING: If the IEnumerable throws an exception during enumeration the stack will be left in a +1 state. You must ensure that no exceptions can be thrown or you must catch them and clean up the stack.</para>
 /// </summary>
 public static void getnestedfield(lua.State L, int index, IEnumerable <string> fields)
 {
     luaL.checkstack(L, 2, "luanet.getnestedfield");
     Debug.Assert(fields != null);                StackAssert.Start(L);
     lua.pushvalue(L, index);
     foreach (string field in fields)
     {
         lua.getfield(L, -1, field);
         lua.remove(L, -2);
     }
     StackAssert.End(1);
 }
Exemple #14
0
 /// <summary>[-0, +0, m] luaL.where clone that returns a string rather than pushing to the stack.</summary>
 public static string where (lua.State L, int level)
 {
     var ar = new lua.Debug();
     if (lua.getstack(L, level, ref ar))                                                  // check function at level
     {
         lua.getinfo(L, "Sl", ref ar);                                                    // get info about it
         if (ar.currentline > 0)                                                          // is there info?
         {
             return(string.Format("{0}:{1}: ", ar.short_src, ar.currentline.ToString())); // tostring here avoids boxing
         }
     }
     return("");             // else, no information available...
 }
Exemple #15
0
        /// <summary>[-0, +1, m] Loads a buffer as a Lua chunk. This function uses <see cref="lua.load"/> to load the chunk in the string s, which can contain embedded zeros. <paramref name="name"/> is the chunk name, used for debug information and error messages.</summary>
        public static LUA.ERR loadbuffer(lua.State L, string s, string name)
        {
            Debug.Assert(s != null);
            var ptr = default(IntPtr);

            try
            {
                ptr = Marshal.StringToHGlobalAnsi(s);
                return(luaL.loadbuffer(L, ptr, s.Length, name));
            }
            catch (OutOfMemoryException) { return((LUA.ERR)luaclr.errormemory(L)); }
            finally { Marshal.FreeHGlobal(ptr); }
        }
Exemple #16
0
        /// <summary>[-0, +0, m] Checks whether the value at the given acceptable index is of the type <paramref name="tname"/> (see <see cref="luaL.newmetatable"/>).</summary>
        public static bool hasmetatable(lua.State L, int index, string tname)
        {
            luaL.checkstack(L, 2, "luanet.hasmetatable");
            if (!lua.getmetatable(L, index))
            {
                return(false);
            }
            lua.getfield(L, LUA.REGISTRYINDEX, tname);
            bool ret = lua.rawequal(L, -1, -2);

            lua.pop(L, 2);
            return(ret);
        }
Exemple #17
0
        /// <summary>[-0, +0, -] Frees a reference created by <see cref="newref"/> so the object can be garbage collected. The value at <paramref name="index"/> MUST be a reference created by <see cref="newref"/>; memory corruption or undefined behavior may result for any other value.<para>The *ref functions are thread-safe; they can used by Lua instances running on different threads.</para></summary>
        public static unsafe void freeref(lua.State L, int index)
        {
            Debug.Assert(luaclr.isreflike(L, index));
            IntPtr *contents = (IntPtr *)lua.touserdata(L, index);
            var     value    = *contents;

            if (value == default(IntPtr))
            {
                return;
            }
            *contents = default(IntPtr);
            GCHandle.FromIntPtr(value).Free();
        }
Exemple #18
0
        /// <summary>[-n, +1, m] Pushes a new C closure onto the stack. <paramref name="n"/> can be up to 254; the last slot is reserved for a garbage collection userdata that keeps the delegate alive.</summary>
        public static void pushcclosure(lua.State L, lua.CFunction f, int n)
        {
            Debug.Assert(f != null);
            Debug.Assert(n <= 254 && n >= 0);
            luaL.checkstack(L, 2, "luaclr.pushcclosure");

            luaclr.newref(L, f);
            luaclr.newrefmeta(L, "LuaCLR CFunction anchor", 0);
            // nothing to add to this metatable other than gc, it just needs to exist and then not exist
            lua.setmetatable(L, -2);

            lua.pushcclosure(L, f, n + 1);
        }
Exemple #19
0
 /// <summary>
 /// <para>[-0, +1, m] <see cref="luaL.newmetatable"/> variant that uses <see cref="newrefmeta(lua.State,int)"/> to create the metatable.</para>
 /// <para>luaL.newmetatable: If the registry already has the key tname, returns false. Otherwise, creates a new table to be used as a metatable for userdata, adds it to the registry with key tname, and returns true. In both cases pushes onto the stack the final value associated with tname in the registry.</para>
 /// <para>luaclr.newrefmeta: Pushes a new table which contains the minimal fields necessary for a properly functioning ref metatable. (__gc and __metatable) <paramref name="field_count"/> is the number of fields you plan to add, so more space can be pre-allocated.</para>
 /// </summary>
 public static bool newrefmeta(lua.State L, string tname, int field_count)
 {
     lua.getfield(L, LUA.REGISTRYINDEX, tname);
     if (lua.istable(L, -1))
     {
         return(false);
     }
     lua.pop(L, 1);
     luaclr.newrefmeta(L, field_count);
     lua.pushvalue(L, -1);
     lua.setfield(L, LUA.REGISTRYINDEX, tname);
     return(true);
 }
Exemple #20
0
        /// <summary><para>[-0, +0, v] Checks whether the function argument <paramref name="narg"/> is a CLR object and returns this object.</para></summary>
        public static object checkref(lua.State L, int narg)
        {
            if (!luaclr.isref(L, narg))
            {
                return(luaL.typerror(L, narg, "CLR object"));
            }
            var o = luaclr.getref(L, narg);

            if (o == null)
            {
                return(luaL.argerror(L, narg, "CLR object reference has been freed"));
            }
            return(o);
        }
Exemple #21
0
        /// <summary>[-0, +1, m] Pushes a new table which contains the minimal fields necessary for a properly functioning ref metatable. (__gc and __metatable) <paramref name="field_count"/> is the number of fields you plan to add, so more space can be pre-allocated.</summary>
        public static void newrefmeta(lua.State L, int field_count)
        {
            luaL.checkstack(L, 3, "luaclr.newrefmeta");
            lua.createtable(L, 0, field_count + 3);

            lua.pushcfunction(L, __gc);
            lua.setfield(L, -2, "__gc");

            lua.pushboolean(L, false);
            lua.setfield(L, -2, "__metatable");

            lua.pushlightuserdata(L, luanet.gettag());
            lua.pushboolean(L, true);
            lua.rawset(L, -3);
        }
Exemple #22
0
        /// <summary>[-0, +0, m] Checks if the value at <paramref name="index"/> is a metatable made by <see cref="newrefmeta(lua.State,int)"/>. See also: <see cref="isref"/></summary>
        public static bool isrefmeta(lua.State L, int index)
        {
            luaL.checkstack(L, 2, "luaclr.isrefmeta");
            index = luanet.absoluteindex(L, index);
            if (!lua.istable(L, index))
            {
                return(false);
            }
            lua.pushlightuserdata(L, luanet.gettag());
            lua.rawget(L, index);
            bool isref = lua.type(L, -1) != LUA.T.NIL;

            lua.pop(L, 1);
            return(isref);
        }
Exemple #23
0
 /// <summary>[-0, +0, -] luaL.where clone that returns a string rather than pushing to the stack.</summary>
 public static string where (lua.State L, int level)
 {
     /*
      *      I checked lua_getinfo implementation and couldn't find any memory allocation for the 'S' or 'l' flags.
      *      My guess is that the luaL_where documentation marked it as m because it uses lua_pushfstring.
      *      - DBN
      */
     var ar = new lua.Debug();
     if (lua.getstack(L, level, ref ar))                                                  // check function at level
     {
         lua.getinfo(L, "Sl", ref ar);                                                    // get info about it
         if (ar.currentline > 0)                                                          // is there info?
         {
             return(string.Format("{0}:{1}: ", ar.short_src, ar.currentline.ToString())); // tostring here avoids boxing
         }
     }
     return("");             // else, no information available...
 }
Exemple #24
0
 /// <summary><para>[-0, +0, v] Checks whether the function argument <paramref name="narg"/> is a CLR object with metatable <paramref name="tname"/> and returns this object.</para><para>This function assumes that <paramref name="tname"/> is a metatable created by luaclr.newrefmeta and does not check it.</para></summary>
 public static object checkref(lua.State L, int narg, string tname)
 {
     if (luaclr.isreflike(L, narg) && lua.getmetatable(L, narg))
     {
         lua.getfield(L, LUA.REGISTRYINDEX, tname);    /* get correct metatable */
         if (lua.rawequal(L, -1, -2))                  /* does it have the correct mt? */
         {
             Debug.Assert(luaclr.isrefmeta(L, -1));
             lua.pop(L, 2);                      /* remove both metatables */
             var o = luaclr.getref(L, narg);
             if (o == null)
             {
                 return(luaL.argerror(L, narg, "CLR object reference has been freed"));
             }
             return(o);
         }
     }
     return(luaL.typerror(L, narg, tname));
 }
Exemple #25
0
        /// <summary>[-0, +0, m] Retrieves the original delegate from a CFunction created by luaclr. Returns null if it is something else. See: <see cref="pushcfunction"/>, <see cref="pushcclosure"/></summary>
        public static lua.CFunction tocfunction(lua.State L, int index)
        {
            luaL.checkstack(L, 2, "luaclr.tocfunction");
            if (!lua.iscfunction(L, index))
            {
                return(null);
            }
            // get the last upvalue, or nil if there are none
            // todo optimization: modify the Lua API to expose upvalue count or do a binary search
            lua.pushnil(L);
            for (int n = 1; n <= 255; ++n)
            {
                if (lua.getupvalue(L, index, n) == null)
                {
                    break;
                }
                lua.remove(L, -2);
            }
            var ret = luaclr.isref(L, -1) ? luaclr.getref(L, -1) as lua.CFunction : null;

            lua.pop(L, 1);
            return(ret);
        }
Exemple #26
0
        /*
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_base   (lua.State L);
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_io     (lua.State L);
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_table  (lua.State L);
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_string (lua.State L);
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_math   (lua.State L);
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_debug  (lua.State L);
         * [DllImport(DLL,CallingConvention=CC)] public static extern void luaopen_loadlib(lua.State L);
         */

        /// <summary>[-0, +1, m] Pushes onto the stack a string identifying the current position of the control at level lvl in the call stack. Typically this string has the following format: <c>chunkname:currentline:</c> Level 0 is the running function, level 1 is the function that called the running function, etc. This function is used to build a prefix for error messages.</summary>
        [DllImport(DLL, CallingConvention = CC, EntryPoint = "luaL_where")] public static extern void where (lua.State L, int level);
Exemple #27
0
 /// <summary>[-0, +0, m] Opens all standard Lua libraries into the given state.</summary>
 [DllImport(DLL, CallingConvention = CC, EntryPoint = "luaL_openlibs")] public static extern void openlibs(lua.State L);
Exemple #28
0
        /// <summary>[-0, +?, m] Loads and runs the given file.</summary>
        [MethodImpl(INLINE)] public static LUA.ERR dofile(lua.State L, string filename)
        {
            var result = luaL.loadfile(L, filename);

            return(result != LUA.ERR.Success ? result : lua.pcall(L, 0, LUA.MULTRET, 0));
        }
Exemple #29
0
        /// <summary>[-0, +?, m] Loads and runs the given string, which can contain embedded zeros.</summary>
        [MethodImpl(INLINE)] public static LUA.ERR dostring(lua.State L, string str)
        {
            var result = luaL.loadstring(L, str);

            return(result != LUA.ERR.Success ? result : lua.pcall(L, 0, LUA.MULTRET, 0));
        }
Exemple #30
0
 /// <summary>[-0, +(0|1), e] Calls a metamethod. If the object at index <paramref name="obj"/> has a metatable and this metatable has a field e, this function calls this field and passes the object as its only argument. In this case this function returns true and pushes onto the stack the value returned by the call. If there is no metatable or no metamethod, this function returns false (without pushing any value on the stack).</summary>
 [DllImport(DLL, CallingConvention = CC, EntryPoint = "luaL_callmeta")] public static extern bool    callmeta(lua.State L, int obj, string e);