summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraunsane <aunsane@gmail.com>2017-09-02 17:27:29 +0300
committeraunsane <aunsane@gmail.com>2017-09-02 17:28:15 +0300
commit478befcb19d3ed1d811f879940d9464f0cab4be5 (patch)
tree77257e80e59281a3ce5a56837f591170fd893211
parent68a501d70e6006464aae627326eda297ebb728eb (diff)
MirLua: added m_enumerable module
-rw-r--r--plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj33
-rw-r--r--plugins/MirLua/Modules/m_enumerable/src/main.cpp440
-rw-r--r--plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx1
-rw-r--r--plugins/MirLua/Modules/m_enumerable/src/stdafx.h12
4 files changed, 486 insertions, 0 deletions
diff --git a/plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj b/plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj
new file mode 100644
index 0000000000..a8e4c9307c
--- /dev/null
+++ b/plugins/MirLua/Modules/m_enumerable/m_enumerable.vcxproj
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>m_enumerable</ProjectName>
+ <ProjectGuid>{82BC22BE-EFA7-4A61-B817-8B1D81080AA4}</ProjectGuid>
+ </PropertyGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(ProjectDir)..\module.props" />
+ </ImportGroup>
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <ExceptionHandling>Sync</ExceptionHandling>
+ </ClCompile>
+ </ItemDefinitionGroup>
+</Project>
diff --git a/plugins/MirLua/Modules/m_enumerable/src/main.cpp b/plugins/MirLua/Modules/m_enumerable/src/main.cpp
new file mode 100644
index 0000000000..709377f589
--- /dev/null
+++ b/plugins/MirLua/Modules/m_enumerable/src/main.cpp
@@ -0,0 +1,440 @@
+#include "stdafx.h"
+
+#define MT_ENUMERABLE "ENUMERABLE"
+
+/***********************************************/
+
+static int lua_WhereIterator(lua_State *L)
+{
+ int enumeratorRef = lua_tointeger(L, lua_upvalueindex(1));
+ int whereRef = lua_tointeger(L, lua_upvalueindex(2));
+
+ int top = lua_gettop(L);
+ while (true)
+ {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+ if (lua_isnoneornil(L, top + 1))
+ {
+ lua_pop(L, nres);
+ break;
+ }
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, whereRef);
+ for (int i = top; i < top + nres; i++)
+ lua_pushvalue(L, i + 1);
+ lua_call(L, nres, 1);
+ if (lua_toboolean(L, -1))
+ {
+ lua_pop(L, 1);
+ return nres;
+ }
+ lua_pop(L, nres + 1);
+ }
+
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int lua_Where(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ lua_pushinteger(L, enumeratorRef);
+ lua_pushvalue(L, 2);
+ lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX));
+ lua_pushcclosure(L, lua_WhereIterator, 2);
+ enumeratorRef = luaL_ref(L, LUA_REGISTRYINDEX);
+ int *udata = (int*)lua_newuserdata(L, sizeof(int));
+ *udata = enumeratorRef;
+ luaL_setmetatable(L, MT_ENUMERABLE);
+
+ return 1;
+}
+
+static int lua_SelectIterator(lua_State *L)
+{
+ int enumeratorRef = lua_tointeger(L, lua_upvalueindex(1));
+ int selectRef = lua_tointeger(L, lua_upvalueindex(2));
+
+ int top = lua_gettop(L);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+ if (lua_isnoneornil(L, top + 1))
+ {
+ lua_pop(L, nres);
+ return 0;
+ }
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, selectRef);
+ lua_insert(L, top + 1);
+ lua_call(L, nres, LUA_MULTRET);
+ nres = lua_gettop(L) - top;
+
+ return nres;
+}
+
+static int lua_Select(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ lua_pushinteger(L, enumeratorRef);
+ lua_pushvalue(L, 2);
+ lua_pushinteger(L, luaL_ref(L, LUA_REGISTRYINDEX));
+ lua_pushcclosure(L, lua_SelectIterator, 2);
+ enumeratorRef = luaL_ref(L, LUA_REGISTRYINDEX);
+ int *udata = (int*)lua_newuserdata(L, sizeof(int));
+ *udata = enumeratorRef;
+ luaL_setmetatable(L, MT_ENUMERABLE);
+
+ return 1;
+}
+
+static int lua_Any(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ bool hasFunc = lua_gettop(L) >= 2;
+ if(hasFunc)
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ int top = lua_gettop(L);
+ while (true)
+ {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+ if (lua_isnoneornil(L, top + 1))
+ {
+ lua_pop(L, nres);
+ break;
+ }
+
+ if (hasFunc)
+ {
+ lua_pushvalue(L, 2);
+ lua_insert(L, top + 1);
+ lua_call(L, nres, 1);
+ nres = lua_gettop(L) - top;
+ if (lua_toboolean(L, -1))
+ {
+ lua_pop(L, nres);
+ lua_pushboolean(L, 1);
+ return 1;
+ }
+ lua_pop(L, nres);
+ continue;
+ }
+
+ lua_pop(L, nres);
+ lua_pushboolean(L, 1);
+
+ return 1;
+ }
+
+ lua_pushboolean(L, 0);
+
+ return 1;
+}
+
+static int lua_First(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ bool hasFunc = lua_gettop(L) >= 2;
+ if (hasFunc)
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ int top = lua_gettop(L);
+ while (true)
+ {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+ if (lua_isnoneornil(L, top + 1))
+ {
+ lua_pop(L, nres);
+ break;
+ }
+
+ if (hasFunc)
+ {
+ lua_pushvalue(L, 2);
+ for (int i = top; i < top + nres; i++)
+ lua_pushvalue(L, i + 1);
+ lua_call(L, nres, 1);
+ if (lua_toboolean(L, -1))
+ {
+ lua_pop(L, 1);
+ return nres;
+ }
+ lua_pop(L, nres + 1);
+ continue;
+ }
+
+ return nres;
+ }
+
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int lua_Last(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ bool hasFunc = lua_gettop(L) >= 2;
+ if (hasFunc)
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+
+ int top = lua_gettop(L);
+ lua_pushnil(L);
+ int nres = lua_gettop(L) - top;
+ while (true)
+ {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int newres = lua_gettop(L) - top - nres;
+ if (lua_isnoneornil(L, top + nres + 1))
+ {
+ lua_pop(L, newres);
+ break;
+ }
+
+ if (hasFunc)
+ {
+ lua_pushvalue(L, 2);
+ for (int i = top + nres; i < top + nres + newres; i++)
+ lua_pushvalue(L, i + 1);
+ lua_call(L, newres, 1);
+ if (!lua_toboolean(L, -1))
+ {
+ lua_pop(L, newres + 1);
+ continue;
+ }
+ lua_pop(L, 1);
+ }
+
+ for (int i = 0; i < nres; i++)
+ lua_remove(L, top + 1);
+ nres = newres;
+ }
+
+ return nres;
+}
+
+static int lua_Count(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+
+ int count = 0;
+ while (true)
+ {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, 1);
+ if (lua_isnoneornil(L, -1))
+ {
+ lua_pop(L, 1);
+ break;
+ }
+
+ lua_pop(L, 1);
+ count++;
+ }
+
+ lua_pushinteger(L, count);
+
+ return 1;
+}
+
+static int lua_ToArray(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+
+ lua_newtable(L);
+ for (int i = 1;; i++)
+ {
+ int top = lua_gettop(L);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+ if (lua_isnoneornil(L, top + 1))
+ {
+ lua_pop(L, nres);
+ break;
+ }
+ lua_rawseti(L, -nres - 1, i);
+ lua_pop(L, nres - 1);
+ }
+
+ return 1;
+}
+
+static int lua_ToTable(lua_State *L)
+{
+ int enumeratorRef = *(int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ luaL_checktype(L, 2, LUA_TFUNCTION);
+ bool hasValueSelectorFunc = lua_gettop(L) >= 3;
+ if (hasValueSelectorFunc)
+ luaL_checktype(L, 3, LUA_TFUNCTION);
+
+ lua_newtable(L);
+ int top = lua_gettop(L);
+ while (true)
+ {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+ if (lua_isnoneornil(L, top + 1))
+ {
+ lua_pop(L, nres);
+ break;
+ }
+
+ lua_pushvalue(L, 2);
+ for (int i = top; i < top + nres; i++)
+ lua_pushvalue(L, i + 1);
+ lua_call(L, nres, 1);
+
+ if (hasValueSelectorFunc)
+ {
+ lua_pushvalue(L, 3);
+ for (int i = top; i < top + nres; i++)
+ lua_pushvalue(L, i + 1);
+ lua_call(L, nres, 1);
+ }
+ else
+ lua_pushvalue(L, top + 1);
+
+ lua_rawset(L, top);
+ lua_pop(L, nres);
+ }
+
+ return 1;
+}
+
+/***********************************************/
+
+static int lua__call(lua_State *L)
+{
+ int *enumeratorRef = (int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+
+ int top = lua_gettop(L);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, *enumeratorRef);
+ lua_call(L, 0, LUA_MULTRET);
+ int nres = lua_gettop(L) - top;
+
+ return nres;
+}
+
+static int lua__pairs(lua_State *L)
+{
+ int *enumeratorRef = (int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, *enumeratorRef);
+
+ return 1;
+}
+
+static int lua__gc(lua_State *L)
+{
+ int *enumeratorRef = (int*)luaL_checkudata(L, 1, MT_ENUMERABLE);
+ luaL_unref(L, LUA_REGISTRYINDEX, *enumeratorRef);
+
+ return 0;
+}
+
+/***********************************************/
+
+static int lua_tableIterator(lua_State *L)
+{
+ lua_pushvalue(L, lua_upvalueindex(1));
+ if (lua_next(L, lua_upvalueindex(2)))
+ {
+ lua_pushvalue(L, -2);
+ lua_replace(L, lua_upvalueindex(1));
+ return 2;
+ }
+
+ lua_pushnil(L);
+
+ return 1;
+}
+
+static int lua__new(lua_State *L)
+{
+ switch (lua_type(L, 1))
+ {
+ case LUA_TTABLE:
+ lua_pushnil(L);
+ lua_pushvalue(L, 1);
+ lua_pushcclosure(L, lua_tableIterator, 2);
+ break;
+ case LUA_TFUNCTION:
+ lua_pushvalue(L, -1);
+ break;
+ default:
+ luaL_argerror(L, 1, luaL_typename(L, 1));
+ }
+
+ int enumeratorRef = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ int *udata = (int*)lua_newuserdata(L, sizeof(int));
+ *udata = enumeratorRef;
+ luaL_setmetatable(L, MT_ENUMERABLE);
+
+ return 1;
+}
+
+/***********************************************/
+
+static luaL_Reg enumerableApi[] =
+{
+ { "Where", lua_Where },
+ { "Select", lua_Select },
+
+ { "Any", lua_Any },
+ { "First", lua_First },
+ { "Last", lua_Last },
+ { "Count", lua_Count },
+
+ { "ToArray", lua_ToArray },
+ { "ToTable", lua_ToTable },
+
+ { NULL, NULL }
+};
+
+static luaL_Reg enumerableMeta[] =
+{
+ { "__call", lua__call },
+ { "__pairs", lua__pairs },
+ { "__gc", lua__gc },
+
+ { NULL, NULL }
+};
+
+static luaL_Reg methods[] =
+{
+ { "new", lua__new },
+
+ { NULL, NULL }
+};
+
+/***********************************************/
+
+extern "C" LUAMOD_API int luaopen_m_enumerable(lua_State *L)
+{
+ luaL_newlib(L, methods);
+
+ luaL_newmetatable(L, MT_ENUMERABLE);
+ luaL_setfuncs(L, enumerableMeta, 0);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+ luaL_setfuncs(L, enumerableApi, 0);
+ lua_pop(L, 1);
+
+ return 1;
+}
diff --git a/plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx b/plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx
new file mode 100644
index 0000000000..fd4f341c7b
--- /dev/null
+++ b/plugins/MirLua/Modules/m_enumerable/src/stdafx.cxx
@@ -0,0 +1 @@
+#include "stdafx.h"
diff --git a/plugins/MirLua/Modules/m_enumerable/src/stdafx.h b/plugins/MirLua/Modules/m_enumerable/src/stdafx.h
new file mode 100644
index 0000000000..5b8469c7fb
--- /dev/null
+++ b/plugins/MirLua/Modules/m_enumerable/src/stdafx.h
@@ -0,0 +1,12 @@
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <windows.h>
+#include <time.h>
+
+#include <lua.hpp>
+
+#include <m_core.h>
+#include <m_utils.h>
+
+#endif //_COMMON_H_ \ No newline at end of file