├── .gitignore ├── ExtTest ├── App.config ├── ExtTest.csproj ├── ExtTest.csproj.vspscc ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── StartEx.cs ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── LuaDLR.sln ├── NeoCmd ├── App.config ├── NeoCmd.csproj ├── NeoCmd.csproj.vspscc ├── Program.cs ├── Properties │ └── AssemblyInfo.cs └── Samples │ ├── Coroutine.lua │ ├── Debug.lua │ ├── FileRead.lua │ ├── ForEach.lua │ ├── Forms.lua │ ├── Forms1.lua │ ├── Hallo.lua │ ├── ModTest.lua │ ├── StringBuilder.lua │ ├── Table.lua │ ├── Test.lua │ ├── file.txt │ └── getPlus.lua ├── NeoLua.Dbg ├── LuaTraceLineDebugger.cs ├── NeoLua.Dbg.csproj └── NeoLua.snk ├── NeoLua.MSBuild ├── Init.ps1 ├── LuaTask.cs ├── LuaTaskFactory.cs ├── NeoLua.MSBuild.csproj ├── Properties │ └── AssemblyInfo.cs └── Sample │ └── Test.bproj ├── NeoLua.NuGet ├── NeoLua.NuGet.csproj ├── NuGet.config ├── build.ps1 ├── common.nupkg.targets ├── common.targets ├── package.targets └── push.ps1 ├── NeoLua.Test ├── CompTests │ ├── bitwise.lua │ ├── calls.lua │ ├── literals.lua │ ├── math.lua │ └── strings.lua ├── Complex.cs ├── ControlStructures.cs ├── Examples.cs ├── Exceptions.cs ├── Expressions.cs ├── Functions.cs ├── Lua │ ├── Control01.lua │ ├── Control02.lua │ ├── Control03.lua │ ├── Control04.lua │ ├── Control05.lua │ ├── Control06.lua │ ├── Control08.lua │ ├── Control09.lua │ ├── Control10.lua │ ├── Control11.lua │ ├── Control12.lua │ ├── Control19.lua │ ├── Control20.lua │ ├── Coroutines01.lua │ ├── Echo.bat │ ├── EnvDynamicCall01.lua │ ├── Function08.lua │ ├── Function08a.lua │ ├── Generics01.lua │ ├── Runtime11.lua │ └── Runtime12.lua ├── LuaEmitTests.cs ├── LuaLibs.cs ├── LuaTable.cs ├── LuaType.cs ├── NeoLua.Test.csproj ├── NeoLua.snk ├── Parser.cs ├── RunLuaTests.cs ├── Runtime.cs └── TestHelper.cs ├── NeoLua ├── Exceptions.cs ├── Extern │ └── printf.cs ├── GlobalSuppressions.cs ├── Lua.Binder.cs ├── Lua.Runtime.cs ├── Lua.cs ├── LuaChunk.cs ├── LuaDebug.cs ├── LuaEmit.cs ├── LuaFile.cs ├── LuaGlobal.cs ├── LuaLexer.cs ├── LuaLibraries.cs ├── LuaResult.cs ├── LuaStackTraceDebugger.cs ├── LuaTable.cs ├── LuaThread.cs ├── LuaType.cs ├── NeoLua.csproj ├── NeoLua.licenseheader ├── NeoLua.snk ├── Parser.Emit.cs ├── Parser.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.de.resx │ └── Resources.resx └── TypeExtensionHelpers.cs ├── NeoSpeed ├── App.config ├── LuaInterface.dll ├── NeoSpeed.csproj ├── NeoSpeed.csproj.vspscc ├── Program.cs ├── Properties │ └── AssemblyInfo.cs ├── Scripts │ ├── CallStd.lua │ ├── Delegate.lua │ ├── Empty.lua │ ├── String.lua │ ├── StringBuilder1.lua │ ├── StringBuilder2.lua │ ├── String_echo.lua │ ├── Sum.lua │ ├── Sum_echo.lua │ ├── Sum_strict1.lua │ ├── Sum_strict2.lua │ ├── TableIntGet.lua │ ├── TableIntSet.lua │ ├── TableString.lua │ ├── TableVsList1.lua │ └── TableVsList2.lua └── lua.dll ├── README.md ├── VBtest ├── App.config ├── Module1.vb ├── Module2.vb ├── My Project │ ├── Application.Designer.vb │ ├── Application.myapp │ ├── AssemblyInfo.vb │ ├── Resources.Designer.vb │ ├── Resources.resx │ ├── Settings.Designer.vb │ └── Settings.settings └── VBtest.vbproj └── doc ├── 02_basics.md ├── 03_language.md ├── 04_01_start.md ├── 04_02_engine.md ├── 04_03_chunk.md ├── 04_04_table.md ├── 05_01_clr.md ├── 05_02_extent.md ├── 05_03_debug.md ├── 06_std.md ├── 07_neocmd.md ├── Codeproject.html ├── Implementation.xlsm └── imgs ├── Image.png ├── done.png ├── noco.png └── noti.png /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studo 2015 cache/options directory 26 | .vs/ 27 | 28 | # MSTest test Results 29 | [Tt]est[Rr]esult*/ 30 | [Bb]uild[Ll]og.* 31 | 32 | # NUNIT 33 | *.VisualState.xml 34 | TestResult.xml 35 | 36 | # Build Results of an ATL Project 37 | [Dd]ebugPS/ 38 | [Rr]eleasePS/ 39 | dlldata.c 40 | 41 | *_i.c 42 | *_p.c 43 | *_i.h 44 | *.ilk 45 | *.meta 46 | *.obj 47 | *.pch 48 | *.pdb 49 | *.pgc 50 | *.pgd 51 | *.rsp 52 | *.sbr 53 | *.tlb 54 | *.tli 55 | *.tlh 56 | *.tmp 57 | *.tmp_proj 58 | *.log 59 | *.vspscc 60 | *.vssscc 61 | .builds 62 | *.pidb 63 | *.svclog 64 | *.scc 65 | 66 | # Chutzpah Test files 67 | _Chutzpah* 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | *.cachefile 76 | 77 | # Visual Studio profiler 78 | *.psess 79 | *.vsp 80 | *.vspx 81 | 82 | # TFS 2012 Local Workspace 83 | $tf/ 84 | 85 | # Guidance Automation Toolkit 86 | *.gpState 87 | 88 | # ReSharper is a .NET coding add-in 89 | _ReSharper*/ 90 | *.[Rr]e[Ss]harper 91 | *.DotSettings.user 92 | 93 | # JustCode is a .NET coding addin-in 94 | .JustCode 95 | 96 | # TeamCity is a build add-in 97 | _TeamCity* 98 | 99 | # DotCover is a Code Coverage Tool 100 | *.dotCover 101 | 102 | # NCrunch 103 | _NCrunch_* 104 | .*crunch*.local.xml 105 | 106 | # MightyMoose 107 | *.mm.* 108 | AutoTest.Net/ 109 | 110 | # Web workbench (sass) 111 | .sass-cache/ 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.[Pp]ublish.xml 131 | *.azurePubxml 132 | # TODO: Comment the next line if you want to checkin your web deploy settings 133 | # but database connection strings (with potential passwords) will be unencrypted 134 | *.pubxml 135 | *.publishproj 136 | 137 | # NuGet Packages 138 | *.nupkg 139 | # The packages folder can be ignored because of Package Restore 140 | **/packages/* 141 | # except build/, which is used as an MSBuild target. 142 | !**/packages/build/ 143 | # Uncomment if necessary however generally it will be regenerated when needed 144 | #!**/packages/repositories.config 145 | 146 | # Windows Azure Build Output 147 | csx/ 148 | *.build.csdef 149 | 150 | # Windows Store app package directory 151 | AppPackages/ 152 | 153 | # Others 154 | *.[Cc]ache 155 | ClientBin/ 156 | [Ss]tyle[Cc]op.* 157 | ~$* 158 | *~ 159 | *.dbmdl 160 | *.dbproj.schemaview 161 | *.pfx 162 | *.publishsettings 163 | node_modules/ 164 | bower_components/ 165 | 166 | # RIA/Silverlight projects 167 | Generated_Code/ 168 | 169 | # Backup & report files from converting an old project file 170 | # to a newer Visual Studio version. Backup files are not needed, 171 | # because we have git ;-) 172 | _UpgradeReport_Files/ 173 | UpgradeLog*.XML 174 | UpgradeLog*.htm 175 | 176 | # SQL Server files 177 | *.mdf 178 | *.ldf 179 | 180 | # Business Intelligence projects 181 | *.rdl.data 182 | *.bim.layout 183 | *.bim_*.settings 184 | 185 | # Microsoft Fakes 186 | FakesAssemblies/ 187 | 188 | # Node.js Tools for Visual Studio 189 | .ntvs_analysis.dat 190 | 191 | # Visual Studio 6 build log 192 | *.plg 193 | 194 | # Visual Studio 6 workspace options file 195 | *.opt 196 | /NeoLua.NuGet/package.apikey.targets 197 | /NeoCmd/Properties/launchSettings.json 198 | -------------------------------------------------------------------------------- /ExtTest/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ExtTest/ExtTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {AE970FAD-2DDB-4FE5-A1B3-8C5E318823D4} 8 | Exe 9 | Properties 10 | ExtTest 11 | ExtTest 12 | v4.8 13 | 512 14 | SAK 15 | SAK 16 | SAK 17 | SAK 18 | 19 | 20 | 21 | AnyCPU 22 | true 23 | full 24 | false 25 | bin\Debug\ 26 | DEBUG;TRACE 27 | prompt 28 | 4 29 | 30 | 31 | AnyCPU 32 | pdbonly 33 | true 34 | bin\Release\ 35 | TRACE 36 | prompt 37 | 4 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | {09aebb35-719e-4e32-9836-f57d7d6f1607} 59 | NeoLua 60 | 61 | 62 | 63 | 70 | -------------------------------------------------------------------------------- /ExtTest/ExtTest.csproj.vspscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" 10 | } 11 | -------------------------------------------------------------------------------- /ExtTest/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Dynamic; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using ExtTest; 7 | using Neo.IronLua; 8 | 9 | namespace NeoTest1 10 | { 11 | //public class Vector3 12 | //{ 13 | // public float X; 14 | // public float Y; 15 | // public float Z; 16 | 17 | // public Vector3(float x, float y, float z) 18 | // { 19 | // X = x; 20 | // Y = y; 21 | // Z = z; 22 | // } 23 | 24 | // public override string ToString() 25 | // { 26 | // return string.Format("X = {0}, Y = {1}, Z = {2}", X, Y, Z); 27 | // } 28 | //} 29 | 30 | 31 | public class Folder 32 | { 33 | public int SomeId { get; set; } 34 | } 35 | 36 | public class File 37 | { 38 | public Folder Folder { get; set; } 39 | } 40 | 41 | public class DynData : DynamicObject 42 | { 43 | public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) 44 | { 45 | return base.TryGetIndex(binder, indexes, out result); 46 | } 47 | 48 | public override bool TryGetMember(GetMemberBinder binder, out object result) 49 | { 50 | if (binder.Name == "Part") 51 | { 52 | result = "Part returned"; 53 | return true; 54 | } 55 | return base.TryGetMember(binder, out result); 56 | } 57 | } 58 | 59 | class Program 60 | { 61 | static async Task TestAsync() 62 | { 63 | await Task.Yield(); 64 | return 0; 65 | } 66 | 67 | #region -- Issue 81 -- 68 | 69 | static bool NegBla(ref MyStruct my) 70 | => !my.Bla; 71 | 72 | struct MyStruct 73 | { 74 | public bool Bla => true; 75 | public bool Awesome => NegBla(ref this); 76 | 77 | } 78 | static MyStruct getStruct() 79 | => new MyStruct(); 80 | 81 | public static void Example() 82 | { 83 | using (var l = new Lua()) 84 | { 85 | dynamic g = l.CreateEnvironment(); 86 | g.t = new LuaTable(); 87 | ((LuaTable)g.t).DefineFunction("getStruct", new Func(getStruct)); 88 | 89 | g.dochunk("local o = t.getStruct(); "+Environment.NewLine+"" + 90 | "print(o.Bla); print(o.Awesome); ", "test.lua"); 91 | } 92 | } 93 | 94 | #endregion 95 | 96 | 97 | static void Main(string[] args) 98 | { 99 | Example(); 100 | 101 | //Console.WriteLine(TestAsync().Result); 102 | 103 | //StartEx.Main1(args); 104 | //TestDynamic(); 105 | 106 | //LinqTest2(); 107 | Console.ReadKey(); 108 | } 109 | 110 | private static void TestDynamic() 111 | { 112 | var lua = new Lua(); 113 | var global = new LuaGlobal(lua) { ["workspace"] = new DynData() }; 114 | 115 | var r = global.DoChunk("return workspace.Part", "Test.lua"); 116 | 117 | Console.WriteLine(r.ToString()); 118 | } 119 | 120 | private static void Test() 121 | { 122 | using (Lua l = new Lua()) 123 | { 124 | var t = new LuaTable(); 125 | var c = l.CompileChunk( 126 | String.Join(Environment.NewLine, 127 | "local v1 = 2;", 128 | "local v2 = 4;", 129 | "function f()", 130 | " return v1 + v2;", 131 | "end;", 132 | "return f();"), "test", null); 133 | var r = c.Run(t); 134 | Console.WriteLine("Test: v1=[{0}], v2=[{1}], r={2}", Lua.RtGetUpValue(t.GetMemberValue("f") as Delegate, 1), Lua.RtGetUpValue(t.GetMemberValue("f") as Delegate, 2), r.ToInt32()); 135 | } 136 | } 137 | 138 | // private static void LinqTest2() 139 | // { 140 | // LuaType.RegisterTypeExtension(typeof(Enumerable)); // generic geht nicht 141 | // List lst = new List(); 142 | // lst.Add(1); 143 | // lst.Add(2); 144 | // lst.Add(3); 145 | // using (Lua l = new Lua()) 146 | // { 147 | // var g = l.CreateEnvironment(); 148 | 149 | // LuaResult r = g.DoChunk(String.Join(Environment.NewLine, 150 | // "return a.Select(function (c) return c; end).ToArray();" 151 | // ), new KeyValuePair("a", lst)); 152 | 153 | // Console.WriteLine(r[0].ToString()); 154 | // } 155 | // } 156 | 157 | // private static void LinqTest() 158 | // { 159 | // LuaTable t = new LuaTable(); 160 | // for (int i = 1; i <= 26; i++) 161 | // t[i] = i * i; 162 | 163 | // string[] arr = t.ArrayList.Select(c => c.ToString()).ToArray(); 164 | 165 | // foreach (string s in arr) 166 | // Console.Write("{0}, ", s); 167 | // } 168 | 169 | // private static void MasterTest() 170 | // { 171 | // using (Lua l = new Lua()) 172 | // { 173 | // dynamic g = l.CreateEnvironment(); 174 | 175 | // g.dofile(@"d:\temp\a\m.lua"); 176 | 177 | // LuaTable t = (LuaTable)g.array; 178 | // Console.WriteLine("{0}", t[1]); 179 | // } 180 | // } 181 | 182 | // private static void Vector3Test() 183 | // { 184 | // string luaScript = @" 185 | //local Vector3 = clr.NeoTest1.Vector3 186 | //local v1 = Vector3(1, 1, 1) 187 | //print(v1) 188 | //local v2 = Vector3(v1.X, v1.Y, v1.Z) 189 | //print(v2) 190 | //"; 191 | // using (Lua lua = new Lua()) 192 | // { 193 | // LuaGlobal lg = lua.CreateEnvironment(); 194 | // try 195 | // { 196 | // lg.DoChunk(luaScript, "dummy.lua"); 197 | // } 198 | // catch (Exception ex) 199 | // { 200 | // Console.WriteLine(ex.Message); 201 | // Console.WriteLine(ex.StackTrace); 202 | // } 203 | // } 204 | // } 205 | } 206 | } -------------------------------------------------------------------------------- /ExtTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die mit einer Assembly verknüpft sind. 8 | [assembly: AssemblyTitle("ExtTest")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ExtTest")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("19371e31-6090-47e6-95e8-d782c54f999f")] 24 | 25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 26 | // 27 | // Hauptversion 28 | // Nebenversion 29 | // Buildnummer 30 | // Revision 31 | // 32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 33 | // übernehmen, indem Sie "*" eingeben: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ExtTest/StartEx.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Neo.IronLua; 8 | 9 | namespace ExtTest 10 | { 11 | class StartEx 12 | { 13 | public const string ProgramSource = "local a, b = tonumber(read(\"a\")), tonumber(read(\"b\"));\n" + 14 | "local PrintResult = function(o, op)\n" + 15 | " print(o.. ' = ' .. a..op..b);\n" + 16 | "end;\n" + 17 | "PrintResult(a + b, \" + \");\n" + 18 | "PrintResult(a - b, \" - \");\n" + 19 | "PrintResult(a * b, \" * \");\n" + 20 | "PrintResult(a / b, \" / \");\n" + 21 | "PrintResult(a // b, \" // \");\n"; 22 | 23 | public static void Main1(string[] args) 24 | { 25 | // create lua script engine 26 | using (var l = new Lua()) 27 | { 28 | // create an environment, that is associated to the lua scripts 29 | dynamic g = l.CreateEnvironment(); 30 | 31 | // register new functions 32 | g.print = new Action(Print); 33 | g.read = new Func(Read); 34 | 35 | 36 | var chunk = l.CompileChunk(ProgramSource, "test.lua", new LuaCompileOptions() { DebugEngine = LuaStackTraceDebugger.Default }); // compile the script with debug informations, that is needed for a complete stack trace 37 | 38 | try 39 | { 40 | g.dochunk(chunk); // execute the chunk 41 | } 42 | catch (Exception e) 43 | { 44 | Console.WriteLine("Expception: {0}", e.Message); 45 | var d = LuaExceptionData.GetData(e); // get stack trace 46 | Console.WriteLine("StackTrace: {0}", d.FormatStackTrace(0, false)); 47 | } 48 | } 49 | } // Main 50 | 51 | private static void Print(object[] texts) 52 | { 53 | foreach (object o in texts) 54 | Console.Write(o); 55 | Console.WriteLine(); 56 | } // proc Print 57 | 58 | private static string Read(string sLabel) 59 | { 60 | Console.Write(sLabel); 61 | Console.Write(": "); 62 | return Console.ReadLine(); 63 | } // func Read 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | NeoLua Version: 2 | 3 | Example to reproduce: 4 | ```Lua 5 | ``` 6 | -------------------------------------------------------------------------------- /NeoCmd/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /NeoCmd/NeoCmd.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | NeoCmd 5 | net48 6 | 7 | Exe 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /NeoCmd/NeoCmd.csproj.vspscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" 10 | } 11 | -------------------------------------------------------------------------------- /NeoCmd/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | [assembly: ComVisible(false)] 4 | [assembly: Guid("549e45af-2f46-4a3d-b745-db189d910a28")] 5 | -------------------------------------------------------------------------------- /NeoCmd/Samples/Coroutine.lua: -------------------------------------------------------------------------------- 1 | function foo(a) 2 | print('foo', a) 3 | return coroutine.yield(2 * a) 4 | end 5 | 6 | co = coroutine.create(function ( a, b ) 7 | print('co-body', a, b) 8 | local r = foo(a + 1) 9 | print('co-body', r) 10 | local r, s = coroutine.yield(a + b, a - b) 11 | print('co-body', r, s) 12 | return b, 'end' 13 | end) 14 | 15 | print('main', coroutine.resume(co, 1, 10)) 16 | print('main', coroutine.resume(co, 'r')) 17 | print('main', coroutine.resume(co, 'x', 'y')) 18 | print('main', coroutine.resume(co, 'x', 'y')) 19 | -------------------------------------------------------------------------------- /NeoCmd/Samples/Debug.lua: -------------------------------------------------------------------------------- 1 | const string typeof System.String; 2 | 3 | function F1(a) 4 | local b = a; 5 | a = a + 1; 6 | print(a, b); 7 | eee(); 8 | end; 9 | 10 | --[[local function FL() 11 | print("Local function."); 12 | end;]] 13 | 14 | F1(2); 15 | --FL(); 16 | -------------------------------------------------------------------------------- /NeoCmd/Samples/FileRead.lua: -------------------------------------------------------------------------------- 1 | do (sw = clr.System.IO.StreamReader([[C:\Projects\NeoLua\trunk\NeoCmd\Samples\FileRead.lua]])) 2 | error("test"); 3 | print(sw:ReadToEnd()); 4 | end; -------------------------------------------------------------------------------- /NeoCmd/Samples/ForEach.lua: -------------------------------------------------------------------------------- 1 | function text() 2 | return "Hallo", "Welt"; 3 | end; 4 | 5 | function test(...) 6 | foreach c in ... do 7 | print(c); 8 | end; 9 | end; 10 | 11 | foreach c in text() do 12 | print(c); 13 | end; -------------------------------------------------------------------------------- /NeoCmd/Samples/Forms.lua: -------------------------------------------------------------------------------- 1 | -- Load Forms 2 | clr.System.Reflection.Assembly:Load("System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 3 | 4 | local Forms = clr.System.Windows.Forms; 5 | local iClicked : int = 0; 6 | 7 | Forms.Application:EnableVisualStyles(); 8 | 9 | do (frm, cmd = Forms.Form(), Forms.Button()) 10 | frm.Text = 'Hallo Welt!'; 11 | cmd.Text = 'Click'; 12 | cmd.Left = 16; 13 | cmd.Top = 16; 14 | cmd.Click:add( 15 | function (sender, e) : void 16 | iClicked = iClicked + 1; 17 | Forms.MessageBox:Show(frm, clr.System.String:Format('Clicked {0:N0} times!', iClicked), 'Lua', Forms.MessageBoxButtons.OK, Forms.MessageBoxIcon.Information); 18 | end); 19 | frm.Controls:Add(cmd); 20 | Forms.Application:Run(frm); 21 | end; -------------------------------------------------------------------------------- /NeoCmd/Samples/Forms1.lua: -------------------------------------------------------------------------------- 1 | const Application typeof System.Windows.Forms.Application; 2 | const Form typeof System.Windows.Forms.Form; 3 | const Button typeof System.Windows.Forms.Button; 4 | const MessageBox typeof System.Windows.Forms.MessageBox; 5 | const MessageBoxButtons typeof System.Windows.Forms.MessageBoxButtons; 6 | const MessageBoxIcon typeof System.Windows.Forms.MessageBoxIcon; 7 | const String typeof System.String; 8 | const Brushes typeof System.Drawing.Brushes; 9 | 10 | local iClicked : int = 0; 11 | 12 | Application:EnableVisualStyles(); 13 | 14 | do (frm : Form, cmd : Button = Form(), Button()) 15 | frm.Text = 'Hallo Welt!'; 16 | cmd.Text = 'Click'; 17 | cmd.Left = 16; 18 | cmd.Top = 16; 19 | cmd.Click:add( 20 | function (sender, e) : void 21 | iClicked = iClicked + 1; 22 | MessageBox:Show(frm, String:Format('Clicked {0:N0} times!', iClicked), 'Lua', MessageBoxButtons.OK, MessageBoxIcon.Information); 23 | end); 24 | frm.Paint:add( 25 | function (sender, e) : void 26 | e.Graphics:FillRectangle(Brushes.Lime, 10, 10, 100, 100); 27 | end); 28 | frm.Controls:Add(cmd); 29 | Application:Run(frm); 30 | end; -------------------------------------------------------------------------------- /NeoCmd/Samples/Hallo.lua: -------------------------------------------------------------------------------- 1 | print("Hallo NeoLua!!!"); -------------------------------------------------------------------------------- /NeoCmd/Samples/ModTest.lua: -------------------------------------------------------------------------------- 1 |  2 | test = {}; 3 | 4 | function test.add(a, b) 5 | return a + b; 6 | end; 7 | 8 | return 1; -------------------------------------------------------------------------------- /NeoCmd/Samples/StringBuilder.lua: -------------------------------------------------------------------------------- 1 | local s = "Hallo Welt"; 2 | local sb = clr.System.Text.StringBuilder(); 3 | 4 | sb:Append(cast(string, string.upper(s))); 5 | 6 | print(sb:ToString()); -------------------------------------------------------------------------------- /NeoCmd/Samples/Table.lua: -------------------------------------------------------------------------------- 1 |  2 | 3 | function test() 4 | local t = {}; 5 | 6 | table.insert(t, "a"); 7 | table.insert(t, "b"); 8 | table.insert(t, "c"); 9 | table.insert(t, "d"); 10 | 11 | print("Table Length: " .. #t); 12 | 13 | return t; 14 | end; 15 | 16 | local t = test(); 17 | 18 | print("Table LengthR: " .. #t); -------------------------------------------------------------------------------- /NeoCmd/Samples/Test.lua: -------------------------------------------------------------------------------- 1 | local e = function () 2 | error("hallo"); 3 | end; 4 | 5 | --e(); 6 | local a, b = tonumber(read("a")), tonumber(read("b")); 7 | 8 | local PrintResult = function (o, op) 9 | 10 | print(o .. ' = ' .. a .. op .. b); 11 | 12 | end; 13 | 14 | PrintResult(a + b, " + "); 15 | PrintResult(a - b, " - "); 16 | PrintResult(a * b, " * "); 17 | PrintResult(a / b, " / "); 18 | PrintResult(a // b, " // "); 19 | -------------------------------------------------------------------------------- /NeoCmd/Samples/file.txt: -------------------------------------------------------------------------------- 1 | hey -------------------------------------------------------------------------------- /NeoCmd/Samples/getPlus.lua: -------------------------------------------------------------------------------- 1 | const StringBuilder typeof System.Text.StringBuilder; 2 | const String typeof System.String; 3 | 4 | function getPlus(lines : int) : String; 5 | local sb = StringBuilder(); 6 | for i = 1,lines,2 do 7 | sb:AppendLine(String('+', i)); 8 | end; 9 | return sb:ToString(); 10 | end; 11 | -------------------------------------------------------------------------------- /NeoLua.Dbg/NeoLua.Dbg.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Neo.Lua.Dbg 5 | Neo.IronLua 6 | true 7 | net452;net60 8 | true 9 | NeoLua.snk 10 | NeoLuaDebug 11 | A Lua implementation for the Dynamic Language Runtime (DLR). Debug-Extension. 12 | Lua C# .net DLR Dynamic Language Debug 13 | 14 | 9 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /NeoLua.Dbg/NeoLua.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoLua.Dbg/NeoLua.snk -------------------------------------------------------------------------------- /NeoLua.MSBuild/Init.ps1: -------------------------------------------------------------------------------- 1 | param($installPath, $toolsPath, $package) 2 | 3 | Write-Host "Copy libs..."; 4 | 5 | if($dte.Solution -and $dte.Solution.IsOpen) 6 | { 7 | $target = Join-Path (Split-Path $dte.Solution.Properties.Item("Path").Value) ".build"; 8 | } 9 | else 10 | { 11 | throw "No solution."; 12 | } 13 | 14 | Write-Host "Target for msbuild task factory: $target"; 15 | if (!(Test-Path $target)) 16 | { 17 | mkdir $target | Out-Null 18 | } 19 | Copy-Item "$toolsPath\Neo.Lua.dll" $target -Force | Out-Null; 20 | Copy-Item "$toolsPath\Neo.Lua.MSBuild.dll" $target -Force | Out-Null; 21 | Write-Host "Copy successful..."; 22 | -------------------------------------------------------------------------------- /NeoLua.MSBuild/LuaTask.cs: -------------------------------------------------------------------------------- 1 | #region -- copyright -- 2 | // 3 | // Licensed to the Apache Software Foundation (ASF) under one 4 | // or more contributor license agreements. See the NOTICE file 5 | // distributed with this work for additional information 6 | // regarding copyright ownership. The ASF licenses this file 7 | // to you under the Apache License, Version 2.0 (the 8 | // "License"); you may not use this file except in compliance 9 | // with the License. You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, 14 | // software distributed under the License is distributed on an 15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. See the License for the 17 | // specific language governing permissions and limitations 18 | // under the License. 19 | // 20 | #endregion 21 | using System; 22 | using System.Collections.Generic; 23 | using System.Linq; 24 | using System.Text; 25 | using Microsoft.Build.Framework; 26 | using Microsoft.Build.Utilities; 27 | 28 | namespace Neo.IronLua 29 | { 30 | /////////////////////////////////////////////////////////////////////////////// 31 | /// 32 | public sealed class LuaTask : Task, IGeneratedTask, IDisposable 33 | { 34 | private LuaChunk chunk; 35 | private LuaGlobal global; 36 | 37 | public LuaTask(LuaChunk chunk) 38 | { 39 | this.chunk = chunk; 40 | this.global = new LuaGlobal(LuaTaskFactory.Lua); 41 | } // ctor 42 | 43 | public void Dispose() 44 | { 45 | chunk = null; 46 | global = null; 47 | } // proc Dispose 48 | 49 | public object GetPropertyValue(TaskPropertyInfo property) 50 | => Lua.RtConvertValue(global[property.Name], property.PropertyType); 51 | 52 | public void SetPropertyValue(TaskPropertyInfo property, object value) 53 | { 54 | global[property.Name] = value; 55 | } // proc SetPropertyValue 56 | 57 | public override bool Execute() 58 | { 59 | try 60 | { 61 | global.DoChunk(chunk, this.BuildEngine, this.Log); 62 | return true; 63 | } 64 | catch (LuaRuntimeException e) 65 | { 66 | Log.LogError("{0} (at line {1},{2})", e.Message, this.chunk.ChunkName, e.Line); 67 | return false; 68 | } 69 | } // func Execute 70 | } // class LuaTask 71 | } 72 | -------------------------------------------------------------------------------- /NeoLua.MSBuild/LuaTaskFactory.cs: -------------------------------------------------------------------------------- 1 | #region -- copyright -- 2 | // 3 | // Licensed to the Apache Software Foundation (ASF) under one 4 | // or more contributor license agreements. See the NOTICE file 5 | // distributed with this work for additional information 6 | // regarding copyright ownership. The ASF licenses this file 7 | // to you under the Apache License, Version 2.0 (the 8 | // "License"); you may not use this file except in compliance 9 | // with the License. You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, 14 | // software distributed under the License is distributed on an 15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. See the License for the 17 | // specific language governing permissions and limitations 18 | // under the License. 19 | // 20 | #endregion 21 | using System; 22 | using System.Collections.Generic; 23 | using System.Linq; 24 | using Microsoft.Build.Framework; 25 | using Microsoft.Build.Utilities; 26 | 27 | namespace Neo.IronLua 28 | { 29 | public sealed class LuaTaskFactory : ITaskFactory 30 | { 31 | private LuaChunk task = null; 32 | private TaskPropertyInfo[] taskProperties = null; 33 | 34 | public bool Initialize(string taskName, IDictionary parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost) 35 | { 36 | var log = new TaskLoggingHelper(taskFactoryLoggingHost, taskName); 37 | 38 | // We use the property group for the declaration 39 | taskProperties = (from c in parameterGroup select c.Value).ToArray(); 40 | 41 | // Compile chunk 42 | try 43 | { 44 | log.LogMessage("Compile script."); 45 | task = Lua.CompileChunk(taskBody, taskName, Lua.StackTraceCompileOptions, 46 | new KeyValuePair("engine", typeof(IBuildEngine)), 47 | new KeyValuePair("log", typeof(TaskLoggingHelper)) 48 | ); 49 | 50 | return true; 51 | } 52 | catch (LuaParseException e) 53 | { 54 | log.LogError("{0} (at line {1},{2})", e.Message, taskName, e.Line); 55 | return false; 56 | } 57 | } // func Initialize 58 | 59 | public ITask CreateTask(IBuildEngine taskFactoryLoggingHost) 60 | => new LuaTask(task); 61 | 62 | public void CleanupTask(ITask task) 63 | => ((LuaTask)task).Dispose(); 64 | 65 | public TaskPropertyInfo[] GetTaskParameters() 66 | => taskProperties; 67 | 68 | public string FactoryName => typeof(LuaTaskFactory).Name; 69 | public Type TaskType => typeof(LuaTask); 70 | 71 | public static Lua Lua { get; } = new Lua(); 72 | } // class LuaTaskFactory 73 | } 74 | -------------------------------------------------------------------------------- /NeoLua.MSBuild/NeoLua.MSBuild.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net451 5 | Write msbuild tasks with NeoLua. 6 | NeoLuaMSBuild 7 | Lua NeoLua .net MSBuild 8 | 9 | 10 | 11 | 12 | 13 | true 14 | tools 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /NeoLua.MSBuild/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | [assembly: ComVisible(false)] 4 | [assembly: Guid("bcd0312a-1eea-4826-9b01-6b84cfb3dde1")] 5 | -------------------------------------------------------------------------------- /NeoLua.MSBuild/Sample/Test.bproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 17 | 18 | 19 | 20 | 21 | Hallo from MSBuild! 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /NeoLua.NuGet/NeoLua.NuGet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | NeoLua.NuGet 6 | NeoLua.NuGet 7 | net451 8 | 9 | 10 | 11 | all 12 | runtime; build; native; contentfiles; analyzers 13 | 14 | 15 | -------------------------------------------------------------------------------- /NeoLua.NuGet/NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NeoLua.NuGet/build.ps1: -------------------------------------------------------------------------------- 1 | & 'C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\msbuild.exe' /t:Restore`;Push /p:Configuration=Debug -------------------------------------------------------------------------------- /NeoLua.NuGet/common.nupkg.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb;.xml 7 | 8 | -------------------------------------------------------------------------------- /NeoLua.NuGet/common.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Neo.Lua 5 | TecWare Gesellschaft für Softwareentwicklung mbH 6 | Copyright © 2013-$([System.DateTime]::Now.Year.ToString()) 7 | Neolithos 8 | 9 | https://github.com/neolithos/neolua/ 10 | https://github.com/neolithos/neolua/blob/master/LICENSE.md 11 | https://github.com/neolithos/neolua.git 12 | git 13 | 14 | 5.3.0.0 15 | 1.3.15.0 16 | 17 | beta.3 18 | ^(\d+)\.(\d+)\.(\d+) 19 | $([System.Text.RegularExpressions.Regex]::Match($(FileVersion), $(SimpleVersionPattern))) 20 | 21 | $(SimpleVersion) 22 | $(SimpleVersion)-$(VersionAdd) 23 | 24 | $(MSBuildThisFileDirectory)bin\$(SimpleVersion) 25 | 26 | 27 | -------------------------------------------------------------------------------- /NeoLua.NuGet/package.targets: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | $(USERPROFILE)\.nuget\packages\msbuildtasks\1.5.0.235\tools 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | true 26 | 27 | 28 | true 29 | 30 | 31 | true 32 | 33 | 34 | false 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 64 | 65 | -------------------------------------------------------------------------------- /NeoLua.NuGet/push.ps1: -------------------------------------------------------------------------------- 1 | & 'C:\Program Files\Microsoft Visual Studio\2022\Professional\MSBuild\Current\Bin\msbuild.exe' /t:Restore`;Push /p:Configuration=Release -------------------------------------------------------------------------------- /NeoLua.Test/CompTests/bitwise.lua: -------------------------------------------------------------------------------- 1 | print("testing bitwise operations") 2 | 3 | assert(bit32.band() == bit32.bnot(0)) 4 | assert(bit32.btest() == true) 5 | assert(bit32.bor() == 0) 6 | assert(bit32.bxor() == 0) 7 | 8 | assert(bit32.band() == bit32.band(0xffffffff)) 9 | assert(bit32.band(1,2) == 0) 10 | 11 | 12 | -- out-of-range numbers 13 | assert(bit32.band(-1) == 0xffffffff) 14 | assert(bit32.band(2^33 - 1) == 0xffffffff) 15 | assert(bit32.band(-2^33 - 1) == 0xffffffff) 16 | assert(bit32.band(2^33 + 1) == 1) 17 | assert(bit32.band(-2^33 + 1) == 1) 18 | assert(bit32.band(-2^40) == 0) 19 | assert(bit32.band(2^40) == 0) 20 | assert(bit32.band(-2^40 - 2) == 0xfffffffe) 21 | assert(bit32.band(2^40 - 4) == 0xfffffffc) 22 | 23 | assert(bit32.lrotate(0, -1) == 0) 24 | assert(bit32.lrotate(0, 7) == 0) 25 | assert(bit32.lrotate(0x12345678, 4) == 0x23456781) 26 | assert(bit32.rrotate(0x12345678, -4) == 0x23456781) 27 | assert(bit32.lrotate(0x12345678, -8) == 0x78123456) 28 | assert(bit32.rrotate(0x12345678, 8) == 0x78123456) 29 | assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa) 30 | assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa) 31 | for i = -50, 50 do 32 | assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32)) 33 | end 34 | 35 | assert(bit32.lshift(0x12345678, 4) == 0x23456780) 36 | assert(bit32.lshift(0x12345678, 8) == 0x34567800) 37 | assert(bit32.lshift(0x12345678, -4) == 0x01234567) 38 | assert(bit32.lshift(0x12345678, -8) == 0x00123456) 39 | assert(bit32.lshift(0x12345678, 32) == 0) 40 | assert(bit32.lshift(0x12345678, -32) == 0) 41 | assert(bit32.rshift(0x12345678, 4) == 0x01234567) 42 | assert(bit32.rshift(0x12345678, 8) == 0x00123456) 43 | assert(bit32.rshift(0x12345678, 32) == 0) 44 | assert(bit32.rshift(0x12345678, -32) == 0) 45 | assert(bit32.arshift(0x12345678, 0) == 0x12345678) 46 | assert(bit32.arshift(0x12345678, 1) == 0x12345678 / 2) 47 | assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2) 48 | assert(bit32.arshift(-1, 1) == 0xffffffff) 49 | assert(bit32.arshift(-1, 24) == 0xffffffff) 50 | assert(bit32.arshift(-1, 32) == 0xffffffff) 51 | -- NeoLua: I do not logic behind this. 52 | --assert(bit32.arshift(-1, -1) == (-1 * 2) % 2^32) 53 | 54 | print("+") 55 | -- some special cases 56 | local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555, 57 | 0xffffffff, 0x7fffffff} 58 | 59 | for _, b in pairs(c) do 60 | assert(bit32.band(b) == b) 61 | assert(bit32.band(b, b) == b) 62 | assert(bit32.btest(b, b) == (b ~= 0)) 63 | assert(bit32.band(b, b, b) == b) 64 | assert(bit32.btest(b, b, b) == (b ~= 0)) 65 | assert(bit32.band(b, bit32.bnot(b)) == 0) 66 | assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0)) 67 | assert(bit32.bor(b) == b) 68 | assert(bit32.bor(b, b) == b) 69 | assert(bit32.bor(b, b, b) == b) 70 | assert(bit32.bxor(b) == b) 71 | assert(bit32.bxor(b, b) == 0) 72 | assert(bit32.bxor(b, 0) == b) 73 | assert(bit32.bnot(b) ~= b) 74 | assert(bit32.bnot(bit32.bnot(b)) == b) 75 | assert(bit32.bnot(b) == 2^32 - 1 - b) 76 | assert(bit32.lrotate(b, 32) == b) 77 | assert(bit32.rrotate(b, 32) == b) 78 | assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf))) 79 | assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf))) 80 | for i = -40, 40 do 81 | assert(bit32.lshift(b, i) == math.floor((b * 2^i) % 2^32)) 82 | end 83 | end 84 | 85 | assert(not pcall(bit32.band, {})) 86 | assert(not pcall(bit32.bnot, "a")) 87 | assert(not pcall(bit32.lshift, 45)) 88 | assert(not pcall(bit32.lshift, 45, print)) 89 | assert(not pcall(bit32.rshift, 45, print)) 90 | 91 | print("+") 92 | 93 | 94 | -- testing extract/replace 95 | 96 | assert(bit32.extract(0x12345678, 0, 4) == 8) 97 | assert(bit32.extract(0x12345678, 4, 4) == 7) 98 | assert(bit32.extract(0xa0001111, 28, 4) == 0xa) 99 | assert(bit32.extract(0xa0001111, 31, 1) == 1) 100 | assert(bit32.extract(0x50000111, 31, 1) == 0) 101 | assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679) 102 | 103 | assert(not pcall(bit32.extract, 0, -1)) 104 | assert(not pcall(bit32.extract, 0, 32)) 105 | assert(not pcall(bit32.extract, 0, 0, 33)) 106 | assert(not pcall(bit32.extract, 0, 31, 2)) 107 | 108 | assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678) 109 | assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321) 110 | assert(bit32.replace(0, 1, 2) == 2^2) 111 | assert(bit32.replace(0, -1, 4) == 2^4) 112 | assert(bit32.replace(-1, 0, 31) == 2^31 - 1) 113 | assert(bit32.replace(-1, 0, 1, 2) == 2^32 - 7) 114 | 115 | 116 | print'OK' 117 | -------------------------------------------------------------------------------- /NeoLua.Test/CompTests/calls.lua: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Based on Lua 5.2.2 test suite 3 | -- 4 | -- http://www.lua.org/tests/5.2/ 5 | -- 6 | print("testing functions and calls") 7 | 8 | -- get the opportunity to test 'type' too ;) 9 | 10 | assert(type(1<2) == 'boolean'); 11 | assert(type(true) == 'boolean' and type(false) == 'boolean'); 12 | assert(type(nil) == 'nil'); 13 | assert(type(-3) == 'number'); 14 | assert(type'x' == 'string'); 15 | assert(type{} == 'table'); 16 | assert(type(type) == 'function'); 17 | 18 | assert(type(assert) == type(print)) 19 | 20 | f = nil 21 | function f (x) return a:x (x) end 22 | assert(type(f) == 'function') 23 | 24 | 25 | -- testing local-function recursion 26 | fact = false 27 | do 28 | local res = 1 29 | local function fact (n) 30 | if n==0 then return res 31 | else return n*fact(n-1) 32 | end 33 | end 34 | assert(fact(5) == 120) 35 | end 36 | assert(fact == false) 37 | 38 | -- testing declarations 39 | a = {i = 10} 40 | self = 20 41 | function a:x (x) return x+self.i end 42 | function a.y (x) return x+self end 43 | 44 | assert(a:x(1)+10 == a.y(1)) 45 | 46 | a.t = {i=-100} 47 | a["t"].x = function (self, a,b) return self.i+a+b end 48 | 49 | assert(a.t:x(2,3) == -95) 50 | 51 | do 52 | local a = {x=0} 53 | function a:add (x) self.x, a.y = self.x+x, 20; return self end 54 | assert(a:add(10):add(20):add(30).x == 60 and a.y == 20) 55 | end 56 | 57 | local a = {b={c={}}} 58 | 59 | function a.b.c.f1 (x) return x+1 end 60 | function a.b.c:f2 (x,y) self[x] = y end 61 | assert(a.b.c.f1(4) == 5) 62 | a.b.c:f2('k', 12); assert(a.b.c.k == 12) 63 | 64 | print('+') 65 | 66 | t = nil -- 'declare' t 67 | function f(a,b,c) local d = 'a'; t={a,b,c,d} end 68 | 69 | f( -- this line change must be valid 70 | 1,2) 71 | assert(t[1] == 1 and t[2] == 2 and t[3] == nil and t[4] == 'a') 72 | f(1,2, -- this one too 73 | 3,4) 74 | assert(t[1] == 1 and t[2] == 2 and t[3] == 3 and t[4] == 'a') 75 | 76 | function fat(x) 77 | if x <= 1 then return 1 78 | else return x*load("return fat(" .. x-1 .. ")")() 79 | end 80 | end 81 | 82 | assert(load "load 'assert(fat(6)==720)' () ")() 83 | a = load('return fat(5), 3') 84 | a,b = a() 85 | assert(a == 120 and b == 3) 86 | print('+') 87 | 88 | function err_on_n (n) 89 | if n==0 then error(); exit(1); 90 | else err_on_n (n-1); exit(1); 91 | end 92 | end 93 | 94 | do 95 | function dummy (n) 96 | if n > 0 then 97 | assert(not pcall(err_on_n, n)) 98 | dummy(n-1) 99 | end 100 | end 101 | end 102 | 103 | dummy(10) 104 | 105 | function deep (n) 106 | if n>0 then deep(n-1) end 107 | end 108 | deep(10) 109 | deep(200) 110 | 111 | -- testing tail call 112 | -- NeoLua: This deep recursions are not possible 113 | function deep (n) if n>0 then return deep(n-1) else return 101 end end 114 | assert(deep(3000) == 101) 115 | a = {} 116 | function a:deep (n) if n>0 then return self:deep(n-1) else return 101 end end 117 | assert(a:deep(300) == 101) 118 | 119 | print('+') 120 | 121 | -- NeoLua: Needs a semicolon, because the grammar is not define clear at this point. 122 | a = nil; 123 | (function (x) a=x end)(23) 124 | assert(a == 23); 125 | assert((function (x) return x*2 end)(20) == 40) 126 | 127 | -- testing closures 128 | 129 | -- fixed-point operator 130 | Z = function (le) 131 | local function a (f) 132 | return le(function (x) return f(f)(x) end) 133 | end 134 | return a(a) 135 | end 136 | 137 | 138 | -- non-recursive factorial 139 | 140 | F = function (f) 141 | return function (n) 142 | if n == 0 then return 1 143 | else return n*f(n-1) end 144 | end 145 | end 146 | 147 | fat = Z(F) 148 | 149 | assert(fat(0) == 1 and fat(4) == 24 and Z(F)(5)==5*Z(F)(4)) 150 | 151 | local function g (z) 152 | local function f (a,b,c,d) 153 | return function (x,y) return a+b+c+d+a+x+y+z end 154 | end 155 | return f(z,z+1,z+2,z+3) 156 | end 157 | 158 | f = g(10) 159 | assert(f(9, 16) == 10+11+12+13+10+9+16+10) 160 | 161 | Z, F, f = nil 162 | print('+') 163 | 164 | -- testing multiple returns 165 | 166 | function unlpack (t, i) 167 | i = i or 1 168 | if (i <= #t) then 169 | return t[i], unlpack(t, i+1) 170 | end 171 | end 172 | 173 | function equaltab (t1, t2) 174 | assert(#t1 == #t2) 175 | for i = 1, #t1 do 176 | assert(t1[i] == t2[i]) 177 | end 178 | end 179 | 180 | local pack = function (...) return (table.pack(...)) end 181 | 182 | function f() return 1,2,30,4 end 183 | function ret2 (a,b) return a,b end 184 | 185 | local a,b,c,d = unlpack{1,2,3} 186 | assert(a==1 and b==2 and c==3 and d==nil) 187 | a = {1,2,3,4,false,10,'alo',false,assert} 188 | equaltab(pack(unlpack(a)), a) 189 | equaltab(pack(unlpack(a), -1), {1,-1}) 190 | a,b,c,d = ret2(f()), ret2(f()) 191 | assert(a==1 and b==1 and c==2 and d==nil) 192 | a,b,c,d = unlpack(pack(ret2(f()), ret2(f()))) 193 | assert(a==1 and b==1 and c==2 and d==nil) 194 | a,b,c,d = unlpack(pack(ret2(f()), (ret2(f())))) 195 | assert(a==1 and b==1 and c==nil and d==nil) 196 | 197 | a = ret2{ unlpack{1,2,3}, unlpack{3,2,1}, unlpack{"a", "b"}} 198 | assert(a[1] == 1 and a[2] == 3 and a[3] == "a" and a[4] == "b") 199 | 200 | 201 | -- testing calls with 'incorrect' arguments 202 | rawget({}, "x", 1) 203 | rawset({}, "x", 1, 2) 204 | assert(math.sin(1,2) == math.sin(1)) 205 | table.sort({10,9,8,4,19,23,0,0}, function (a,b) return a 10e30) 29 | assert(-math.huge < -10e30) 30 | end 31 | 32 | function f(...) 33 | local c = select('#', ...); -- NeoLua: Empty table is like one 34 | if c == 0 or c == 1 then 35 | return (...) 36 | else 37 | return "***" 38 | end 39 | end 40 | 41 | 42 | -- testing numeric strings 43 | 44 | assert("2" + 1 == 3) 45 | assert("2 " + 1 == 3) 46 | assert(" -2 " + 1 == -1) 47 | assert(" -0xa " + 1 == -9) 48 | 49 | 50 | -- testing 'tonumber' 51 | assert(tonumber{} == nil) 52 | assert(tonumber'+0.01' == 1/100 and tonumber'+.01' == 0.01 and 53 | tonumber'.01' == 0.01 and tonumber'-1.' == -1 and 54 | tonumber'+1.' == 1) 55 | assert(tonumber'+ 0.01' == nil); 56 | assert(tonumber'+.e1' == nil) 57 | assert(tonumber'1e' == nil); 58 | assert(tonumber'1.0e+' == nil); 59 | assert(tonumber'.' == nil); 60 | assert(tonumber('-012') == -010-2) 61 | assert(tonumber('-1.2e2') == - - -120.0) 62 | 63 | assert(tonumber("0xffffffffffff") == 2^(4*12) - 1) 64 | assert(tonumber("0x"..string.rep("f", 150)) == 2^(4*150) - 1) 65 | assert(tonumber('0x3.' .. string.rep('0', 100)) == 3) 66 | assert(tonumber('0x0.' .. string.rep('0', 150).."1") == 2^(-4*151)) 67 | 68 | -- testing 'tonumber' with base 69 | assert(tonumber(' 001010 ', 2) == 10) 70 | assert(tonumber(' 001010 ', 10) == 001010) 71 | assert(tonumber(' -1010 ', 2) == -10) 72 | assert(tonumber('10', 36) == 36) 73 | assert(tonumber(' -10 ', 36) == -36) 74 | assert(tonumber(' +1Z ', 36) == 36 + 35) 75 | assert(tonumber(' -1z ', 36) == -36 + -35) 76 | assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15))))))) 77 | assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42) 78 | assert(tonumber(string.rep('1', 34), 2) + 1 == 2^34) 79 | assert(tonumber('ffffFFFF', 16)+1 == 2^32) 80 | assert(tonumber('0ffffFFFF', 16)+1 == 2^32) 81 | assert(tonumber('-0ffffffFFFF', 16) - 1 == -2^40) 82 | for i = 2,36 do 83 | assert(tonumber('\t10000000000\t', i) == i^10) 84 | end 85 | 86 | -- testing 'tonumber' fo invalid formats 87 | assert(f(tonumber('fFfa', 15)) == nil) 88 | assert(f(tonumber('099', 8)) == nil) 89 | -- NeoLua: \0 is a whitespace 90 | --assert(f(tonumber('1\0', 2)) == nil) 91 | assert(f(tonumber('', 8)) == nil) 92 | assert(f(tonumber(' ', 9)) == nil) 93 | assert(f(tonumber(' ', 9)) == nil) 94 | assert(f(tonumber('0xf', 10)) == nil) 95 | 96 | assert(f(tonumber('inf')) == nil) 97 | assert(f(tonumber(' INF ')) == nil) 98 | assert(f(tonumber('Nan')) == nil) 99 | assert(f(tonumber('nan')) == nil) 100 | 101 | assert(f(tonumber(' ')) == nil) 102 | assert(f(tonumber('')) == nil) 103 | assert(f(tonumber('1 a')) == nil) 104 | assert(f(tonumber('1\0')) == nil) 105 | assert(f(tonumber('1 \0')) == nil) 106 | assert(f(tonumber('1\0 ')) == nil) 107 | assert(f(tonumber('e1')) == nil) 108 | assert(f(tonumber('e 1')) == nil) 109 | assert(f(tonumber(' 3.4.5 ')) == nil) 110 | 111 | 112 | -- testing 'tonumber' for invalid hexadecimal formats 113 | 114 | assert(tonumber('0x') == nil) 115 | assert(tonumber('x') == nil) 116 | assert(tonumber('x3') == nil) 117 | assert(tonumber('00x2') == nil) 118 | assert(tonumber('0x 2') == nil) 119 | assert(tonumber('0 x2') == nil) 120 | assert(tonumber('23x') == nil) 121 | assert(tonumber('- 0xaa') == nil) 122 | 123 | 124 | -- testing hexadecimal numerals 125 | 126 | assert(0x10 == 16 and 0xfff == 2^12 - 1 and 0XFB == 251) 127 | assert(0x0p12 == 0 and 0x.0p-3 == 0) 128 | assert(0xFFFFFFFF == 2^32 - 1) 129 | assert(tonumber('+0x2') == 2) 130 | assert(tonumber('-0xaA') == -170) 131 | assert(tonumber('-0xffFFFfff') == -2^32 + 1) 132 | 133 | -- possible confusion with decimal exponent 134 | assert(0E+1 == 0 and 0xE+1 == 15 and 0xe-1 == 13) 135 | 136 | 137 | -- floating hexas 138 | 139 | assert(tonumber(' 0x2.5 ') == 0x25/16) 140 | assert(tonumber(' -0x2.5 ') == -0x25/16) 141 | assert(tonumber(' +0x0.51p+8 ') == 0x51) 142 | assert(tonumber('0x0.51p') == nil) 143 | assert(tonumber('0x5p+-2') == nil) 144 | assert(0x.FfffFFFF == 1 - '0x.00000001') 145 | assert('0xA.a' + 0 == 10 + 10/16) 146 | assert(0xa.aP4 == 0XAA) 147 | assert(0x4P-2 == 1) 148 | assert(0x1.1 == '0x1.' + '+0x.1') 149 | 150 | assert(1.1 == 1.+.1) 151 | assert(100.0 == 1E2 and .01 == 1e-2) 152 | assert(1111111111111111-1111111111111110== 1000.00e-03) 153 | -- 1234567890123456 154 | assert(1.1 == '1.'+'.1') 155 | assert('1111111111111111'-'1111111111111110' == tonumber" +0.001e+3 \n\t") 156 | 157 | function eq (a,b,limit) 158 | if not limit then limit = 10E-10 end 159 | return math.abs(a-b) <= limit 160 | end 161 | 162 | assert(0.1e-30 > 0.9E-31 and 0.9E30 < 0.1e31) 163 | 164 | assert(0.123456 > 0.123455) 165 | 166 | assert(tonumber('+1.23E18') == 1.23*10^18) 167 | 168 | -- testing order operators 169 | assert(not(1<1) and (1<2) and not(2<1)) 170 | assert(not('a'<'a') and ('a'<'b') and not('b'<'a')) 171 | assert((1<=1) and (1<=2) and not(2<=1)) 172 | assert(('a'<='a') and ('a'<='b') and not('b'<='a')) 173 | assert(not(1>1) and not(1>2) and (2>1)) 174 | assert(not('a'>'a') and not('a'>'b') and ('b'>'a')) 175 | assert((1>=1) and not(1>=2) and (2>=1)) 176 | assert(('a'>='a') and not('a'>='b') and ('b'>='a')) 177 | 178 | -- testing mod operator 179 | -- NeoLua: I do not logic behind this. 180 | --assert(-4%3 == 2) 181 | --assert(4%-3 == -2) 182 | assert(-4%3 == -1) 183 | assert(4%-3 == 1) 184 | assert(math.pi - math.pi % 1 == 3) 185 | assert(math.pi - math.pi % 0.001 == 3.141) 186 | 187 | local function testbit(a, n) 188 | return a/2^n % 2 >= 1 189 | end 190 | 191 | assert(eq(math.sin(-9.8)^2 + math.cos(-9.8)^2, 1)) 192 | assert(eq(math.tan(math.pi/4), 1)) 193 | assert(eq(math.sin(math.pi/2), 1) and eq(math.cos(math.pi/2), 0)) 194 | assert(eq(math.atan(1), math.pi/4) and eq(math.acos(0), math.pi/2) and 195 | eq(math.asin(1), math.pi/2)) 196 | assert(eq(math.deg(math.pi/2), 90) and eq(math.rad(90), math.pi/2)) 197 | assert(math.abs(-10) == 10) 198 | assert(eq(math.atan2(1,0), math.pi/2)) 199 | assert(math.ceil(4.5) == 5.0) 200 | assert(math.floor(4.5) == 4.0) 201 | assert(math.fmod(10,3) == 1) 202 | assert(eq(math.sqrt(10)^2, 10)) 203 | assert(eq(math.log(2, 10), math.log(2)/math.log(10))) 204 | assert(eq(math.log(2, 2), 1)) 205 | assert(eq(math.log(9, 3), 2)) 206 | assert(eq(math.exp(0), 1)) 207 | assert(eq(math.sin(10), math.sin(10%(2*math.pi)))) 208 | local v,e = math.frexp(math.pi) 209 | assert(eq(math.ldexp(v,e), math.pi)) 210 | 211 | assert(eq(math.tanh(3.5), math.sinh(3.5)/math.cosh(3.5))) 212 | 213 | assert(tonumber(' 1.3e-2 ') == 1.3e-2) 214 | assert(tonumber(' -1.00000000000001 ') == -1.00000000000001) 215 | 216 | -- testing constant limits 217 | -- 2^23 = 8388608 218 | assert(8388609 + -8388609 == 0) 219 | assert(8388608 + -8388608 == 0) 220 | assert(8388607 + -8388607 == 0) 221 | 222 | -- testing implicit convertions 223 | 224 | local a,b = '10', '20' 225 | assert(a*b == 200 and a+b == 30 and a-b == -10 and a/b == 0.5 and -b == -20) 226 | assert(a == '10' and b == '20') 227 | 228 | 229 | --if not _port then 230 | --print("testing -0 and NaN") 231 | --local mz, z = -0, 0 232 | --assert(mz == z) 233 | --assert(1/mz < 0 and 0 < 1/z) 234 | --local a = {[mz] = 1} 235 | --assert(a[z] == 1 and a[mz] == 1) 236 | --local inf = math.huge * 2 + 1 237 | --mz, z = -1/inf, 1/inf 238 | --assert(mz == z) 239 | --assert(1/mz < 0 and 0 < 1/z) 240 | --local NaN = inf - inf 241 | --assert(NaN ~= NaN) 242 | --assert(not (NaN < NaN)) 243 | --assert(not (NaN <= NaN)) 244 | --assert(not (NaN > NaN)) 245 | --assert(not (NaN >= NaN)) 246 | --assert(not (0 < NaN) and not (NaN < 0)) 247 | --local NaN1 = 0/0 248 | --assert(NaN ~= NaN1 and not (NaN <= NaN1) and not (NaN1 <= NaN)) 249 | --local a = {} 250 | --assert(not pcall(function () a[NaN] = 1 end)) 251 | --assert(a[NaN] == nil) 252 | --a[1] = 1 253 | --assert(not pcall(function () a[NaN] = 1 end)) 254 | --assert(a[NaN] == nil) 255 | ---- string with same binary representation as 0.0 (may create problems 256 | ---- for constant manipulation in the pre-compiler) 257 | --local a1, a2, a3, a4, a5 = 0, 0, "\0\0\0\0\0\0\0\0", 0, "\0\0\0\0\0\0\0\0" 258 | --assert(a1 == a2 and a2 == a4 and a1 ~= a3) 259 | --assert(a3 == a5) 260 | --end 261 | 262 | --if not _port then 263 | --print("testing 'math.random'") 264 | --math.randomseed(0) 265 | -- 266 | --local function aux (x1, x2, p) 267 | --local Max = -math.huge 268 | --local Min = math.huge 269 | --for i = 0, 20000 do 270 | --local t = math.random(table.unpack(p)) 271 | --Max = math.max(Max, t) 272 | --Min = math.min(Min, t) 273 | --if eq(Max, x2, 0.001) and eq(Min, x1, 0.001) then 274 | --goto ok 275 | --end 276 | --end 277 | ---- loop ended without satisfing condition 278 | --assert(false) 279 | --::ok:: 280 | --assert(x1 <= Min and Max<=x2) 281 | --end 282 | -- 283 | --aux(0, 1, {}) 284 | --aux(-10, 0, {-10,0}) 285 | --end 286 | -- 287 | for i=1,10 do 288 | local t = math.random(5) 289 | assert(1 <= t and t <= 5) 290 | end 291 | 292 | 293 | print('OK') 294 | -------------------------------------------------------------------------------- /NeoLua.Test/CompTests/strings.lua: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoLua.Test/CompTests/strings.lua -------------------------------------------------------------------------------- /NeoLua.Test/Complex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | using Neo.IronLua; 10 | 11 | namespace LuaDLR.Test 12 | { 13 | public class ComplexTestClass 14 | { 15 | public static T GenericSimple(T i) 16 | { 17 | return i; 18 | } // proc Test 19 | 20 | public static string GenericSimple(string i) 21 | { 22 | return i; 23 | } // proc Test 24 | } // class ComplexTestClass 25 | 26 | [TestClass] 27 | public class ComplexStructures : TestHelper 28 | { 29 | [TestMethod] 30 | public void Generics01() 31 | { 32 | TestCode(GetLines("Lua.Generics01.lua"), 3); 33 | } // proc Generics01 34 | 35 | [TestMethod] 36 | public void Generics02() 37 | { 38 | TestCode("return clr.LuaDLR.Test.ComplexTestClass:GenericSimple(3)", 3); 39 | TestCode("return clr.LuaDLR.Test.ComplexTestClass:GenericSimple('3')", "3"); 40 | } // proc Generics02 41 | 42 | private delegate string TestDelegate(int value); 43 | 44 | [TestMethod] 45 | public void Delegate01() 46 | { 47 | using (Lua l = new Lua()) 48 | { 49 | l.PrintExpressionTree = Console.Out; 50 | TestDelegate dlg = l.CreateLambda("Test", "return value:ToString();"); 51 | string sR = dlg(3); 52 | Assert.IsTrue(sR == "3"); 53 | } 54 | } // proc Delegate01 55 | 56 | [TestMethod] 57 | public void Delegate02() 58 | { 59 | using (Lua l = new Lua()) 60 | { 61 | l.PrintExpressionTree = Console.Out; 62 | var dlg = l.CreateLambda>("Test", "return arg1 + arg2"); 63 | Assert.IsTrue(dlg(1, 2) == 3); 64 | } 65 | } // proc Delegate02 66 | 67 | [TestMethod] 68 | public void Delegate03() 69 | { 70 | using (Lua l = new Lua()) 71 | { 72 | l.PrintExpressionTree = Console.Out; 73 | var dlg = l.CreateLambda>("Test", "return a + b", "a", "b"); 74 | Assert.IsTrue(dlg(1, 2) == 3); 75 | } 76 | } // proc Delegate03 77 | 78 | [TestMethod] 79 | public void Coroutines01() 80 | { 81 | TestCode(GetLines("Lua.Coroutines01.lua")); 82 | } 83 | 84 | [DataTestMethod] 85 | [DataRow("return clr.System.String:Format(\"{0}\", values[0]);", "1.1")] 86 | [DataRow("return clr.System.String:Format(\"{0}; {1}; {2}; {3}\", values);", "1.1; 2.2; 3.3; 4.4")] 87 | [DataRow("return clr.System.String:Format(clr.System.Globalization.CultureInfo.InvariantCulture, \"{0}; {1}; {2}; {3}\", values);", "1.1; 2.2; 3.3; 4.4")] 88 | public void StringFormat01(string code, string expectedResult) 89 | { 90 | object[] values = { 1.1, 2.2, 3.3, 4.4 }; 91 | var culture = Thread.CurrentThread.CurrentCulture; 92 | try 93 | { 94 | using (Lua l = new Lua()) 95 | { 96 | //l.PrintExpressionTree =Console.Out; 97 | var g = l.CreateEnvironment(); 98 | Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; 99 | 100 | g.SetMemberValue("values", values); 101 | 102 | TestResult(g.DoChunk(code, "test0.lua"), expectedResult); 103 | } 104 | } 105 | finally 106 | { 107 | Thread.CurrentThread.CurrentCulture = culture; 108 | } 109 | } 110 | 111 | [TestMethod] 112 | public void NumberToString01() 113 | { 114 | object[] values = new object[] { 1.1 }; 115 | 116 | using (Lua l = new Lua()) 117 | { 118 | l.PrintExpressionTree = Console.Out; 119 | var g = l.CreateEnvironment(); 120 | 121 | g.SetMemberValue("values", values); 122 | 123 | TestResult(g.DoChunk("return values[0]:ToString();", "test0.lua"), values[0].ToString()); 124 | TestResult(g.DoChunk("return values[0]:ToString(\"G\");", "test0.lua"), ((double)values[0]).ToString("G")); 125 | TestResult(g.DoChunk("return values[0]:ToString(\"G\", clr.System.Globalization.CultureInfo.InvariantCulture);", "test0.lua"), ((double)values[0]).ToString("G", System.Globalization.CultureInfo.InvariantCulture)); 126 | } 127 | } 128 | 129 | [TestMethod] 130 | public void StackTracer01() 131 | { 132 | using (var l = new Lua()) 133 | { 134 | l.PrintExpressionTree = Console.Out; 135 | var c = l.CompileChunk(Lines( 136 | "a = {};", 137 | "function a:m(a, b)", 138 | "return a .. ' - ' .. b;", 139 | "end;", 140 | 141 | "return a:m(1, 'a'),a:m('1', 2);"), "test.lua", Lua.StackTraceCompileOptions); 142 | var g = l.CreateEnvironment(); 143 | TestResult(g.DoChunk(c), "1 - a", "1 - 2"); 144 | } 145 | } 146 | 147 | 148 | } // class ComplexStructures 149 | } 150 | -------------------------------------------------------------------------------- /NeoLua.Test/ControlStructures.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.VisualStudio.TestTools.UnitTesting; 7 | using Neo.IronLua; 8 | 9 | namespace LuaDLR.Test 10 | { 11 | [TestClass] 12 | public class ControlStructures : TestHelper 13 | { 14 | public class CompareMe : IComparable, IComparable, IComparable 15 | { 16 | private int i; 17 | 18 | public CompareMe(int i) 19 | { 20 | this.i = i; 21 | } 22 | 23 | public int CompareTo(int other) 24 | { 25 | return i - other; 26 | } 27 | 28 | public int CompareTo(CompareMe other) 29 | { 30 | return i - other.i; 31 | } 32 | 33 | public int CompareTo(object obj) 34 | { 35 | if (obj is CompareMe) 36 | return i - ((CompareMe)obj).i; 37 | else if (obj is int) 38 | return i - (int)obj; 39 | else 40 | return -1; 41 | } 42 | 43 | public override bool Equals(object obj) 44 | { 45 | return CompareTo(obj) == 0; 46 | } 47 | 48 | public override int GetHashCode() 49 | { 50 | return i.GetHashCode(); 51 | } 52 | 53 | //public static int operator +(CompareMe a, CompareMe b) 54 | //{ 55 | // return a.i + b.i; 56 | //} 57 | 58 | //public static implicit operator CompareMe(int a) 59 | //{ 60 | // return new CompareMe(a); 61 | //} 62 | 63 | //public static implicit operator int(CompareMe a) 64 | //{ 65 | // return a.i; 66 | //} 67 | 68 | //public static CompareMe operator -(CompareMe a, CompareMe b) 69 | //{ 70 | // return new CompareMe(a.i - b.i); 71 | //} 72 | 73 | //public static CompareMe operator *(CompareMe a, CompareMe b) 74 | //{ 75 | // return new CompareMe(a.i * b.i); 76 | //} 77 | 78 | //public static CompareMe operator /(CompareMe a, CompareMe b) 79 | //{ 80 | // return new CompareMe(a.i / b.i); 81 | //} 82 | 83 | //public static CompareMe operator %(CompareMe a, CompareMe b) 84 | //{ 85 | // return new CompareMe(a.i % b.i); 86 | //} 87 | 88 | //public static bool operator ==(CompareMe a, CompareMe b) 89 | //{ 90 | // return a.i == b.i; 91 | //} 92 | 93 | //public static bool operator !=(CompareMe a, CompareMe b) 94 | //{ 95 | // return a.i != b.i; 96 | //} 97 | 98 | //public static bool operator <=(CompareMe a, CompareMe b) 99 | //{ 100 | // return a.i <= b.i; 101 | //} 102 | 103 | //public static bool operator >=(CompareMe a, CompareMe b) 104 | //{ 105 | // return a.i >= b.i; 106 | //} 107 | 108 | //public static bool operator <(CompareMe a, CompareMe b) 109 | //{ 110 | // return a.i < b.i; 111 | //} 112 | 113 | //public static bool operator >(CompareMe a, CompareMe b) 114 | //{ 115 | // return a.i > b.i; 116 | //} 117 | 118 | //public static CompareMe operator &(CompareMe a, CompareMe b) 119 | //{ 120 | // return a.i & b.i; 121 | //} 122 | 123 | //public static CompareMe operator |(CompareMe a, CompareMe b) 124 | //{ 125 | // return a.i | b.i; 126 | //} 127 | 128 | ////+, -, !, ~, ++, --, true, false 129 | ////+, -, *, /, %, &, | , ^, <<, >> 130 | ////==, !=, <, >, <=, >= 131 | 132 | //public static CompareMe operator ++(CompareMe a) 133 | //{ 134 | // a.i++; 135 | // return a; 136 | //} 137 | 138 | //public static CompareMe operator --(CompareMe a) 139 | //{ 140 | // a.i--; 141 | // return a; 142 | //} 143 | } 144 | 145 | [TestMethod] 146 | public void Control01() 147 | { 148 | TestCode(GetLines("Lua.Control01.lua"), 3); 149 | } 150 | 151 | [TestMethod] 152 | public void Control02() 153 | { 154 | TestCode(GetLines("Lua.Control02.lua"), 10); 155 | } 156 | 157 | [TestMethod] 158 | public void Control03() 159 | { 160 | TestCode(GetLines("Lua.Control03.lua"), 10); 161 | } 162 | 163 | [TestMethod] 164 | public void Control04() 165 | { 166 | TestCode(GetLines("Lua.Control04.lua"), 4); 167 | } 168 | 169 | [TestMethod] 170 | public void Control05() 171 | { 172 | TestCode(GetLines("Lua.Control05.lua"), 10); 173 | } 174 | 175 | [TestMethod] 176 | public void Control06() 177 | { 178 | TestCode(GetLines("Lua.Control06.lua"), 55); 179 | } 180 | 181 | [TestMethod] 182 | public void Control07() 183 | { 184 | TestCode("return;"); 185 | } 186 | 187 | [TestMethod] 188 | public void Control08() 189 | { 190 | TestCode(GetLines("Lua.Control08.lua"), 4321); 191 | } 192 | 193 | [TestMethod] 194 | public void Control09() 195 | { 196 | TestCode(GetLines("Lua.Control09.lua"), 4321); 197 | } 198 | 199 | [TestMethod] 200 | public void Control10() 201 | { 202 | TestCode(GetLines("Lua.Control10.lua"), 4321); 203 | } 204 | 205 | [TestMethod] 206 | public void Control11() 207 | { 208 | TestCode(GetLines("Lua.Control11.lua"), 6); 209 | } 210 | 211 | [TestMethod] 212 | public void Control12() 213 | { 214 | TestCode(Lines( 215 | "local s = 0;", 216 | "for i = 1, 100, 0.1 do", 217 | " s = s + i;", 218 | "end;", 219 | "return s;"), 50045.5); 220 | } 221 | 222 | [TestMethod] 223 | public void Control13() 224 | { 225 | TestCode(Lines( 226 | "do", 227 | " error('test');", 228 | "end(", 229 | " function (e)", 230 | " return e.Message;", 231 | " end", 232 | ")"), "test" 233 | ); 234 | } 235 | 236 | [TestMethod] 237 | public void Control14() 238 | { 239 | TestCode(Lines( 240 | "do", 241 | " error('test');", 242 | "end(", 243 | " function (e : System.ArgumentException)", 244 | " return 'err1';", 245 | " end,", 246 | " function (e)", 247 | " return 'err2';", 248 | " end,", 249 | ")"), "err2" 250 | ); 251 | TestCode(Lines( 252 | "do", 253 | " return 'test':Substring(-10);", 254 | "end(", 255 | " function (e : System.ArgumentException)", 256 | " return 'err1';", 257 | " end,", 258 | " function (e)", 259 | " return 'err2';", 260 | " end,", 261 | ")"), "err1" 262 | ); 263 | 264 | // 2. catch will ignored 265 | TestCode(Lines( 266 | "do", 267 | " return 'test':Substring(-10);", 268 | "end(", 269 | " function (e)", 270 | " return 'err2';", 271 | " end,", 272 | " function (e : System.ArgumentException)", 273 | " return 'err1';", 274 | " end", 275 | ")"), "err2" 276 | ); 277 | } 278 | 279 | [TestMethod] 280 | public void Control15() 281 | { 282 | try 283 | { 284 | TestCode(Lines( 285 | "do", 286 | " error('test');", 287 | "end(", 288 | " function (e)", 289 | " rethrow;", 290 | " end", 291 | ")"), "test" 292 | ); 293 | Assert.Fail(); 294 | } 295 | catch (LuaRuntimeException) 296 | { 297 | } 298 | catch 299 | { 300 | Assert.Fail(); 301 | } 302 | } 303 | 304 | [TestMethod] 305 | public void Control16() 306 | { 307 | TestCode(Lines( 308 | "do", 309 | " error('test');", 310 | " return 'noerr';", 311 | "end(", 312 | " function (e)", 313 | " return 'err'", 314 | " end", 315 | ")"), "err" 316 | ); 317 | } 318 | 319 | [TestMethod] 320 | public void Control17() 321 | { 322 | TestCode(Lines( 323 | "local a = 'a1';", 324 | "do", 325 | " error('test');", 326 | "end(", 327 | " function (e)", 328 | " a = 'a2'", 329 | " end,", 330 | " function", 331 | " a = 'a3'", 332 | " end", 333 | ")", 334 | " return a;" 335 | ), "a3" 336 | ); 337 | } 338 | 339 | [TestMethod] 340 | public void Control18() 341 | { 342 | TestCode(Lines( 343 | "local a = 'a1';", 344 | "do (b = 'aaaa')", 345 | " error('test ' .. b);", 346 | "end(", 347 | " function (e)", 348 | " a = 'a2'", 349 | " end,", 350 | " function", 351 | " a = 'a3' .. b", 352 | " end", 353 | ")", 354 | " return a;" 355 | ), "a3aaaa" 356 | ); 357 | } 358 | 359 | [TestMethod] 360 | public void Control19() 361 | { 362 | TestCode(GetLines("Lua.Control19.lua"), 4); 363 | } 364 | 365 | [TestMethod] 366 | public void Control20() 367 | { 368 | TestCode(GetLines("Lua.Control20.lua"), 500000500000, 500000500001); 369 | } 370 | 371 | [TestMethod] 372 | public void TestVariableAssign01() 373 | { 374 | TestCode(Lines( 375 | "local type = type;", 376 | "return type(2);"), "number"); 377 | } 378 | } // class ControlStructures 379 | } 380 | -------------------------------------------------------------------------------- /NeoLua.Test/Exceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Dynamic; 5 | using System.Linq; 6 | using System.Linq.Expressions; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using Microsoft.VisualStudio.TestTools.UnitTesting; 11 | using Neo.IronLua; 12 | 13 | namespace LuaDLR.Test 14 | { 15 | [TestClass] 16 | public class Exceptions : TestHelper 17 | { 18 | [TestMethod] 19 | public void Exception01() 20 | { 21 | using (Lua l = new Lua()) 22 | { 23 | var g = l.CreateEnvironment(); 24 | try 25 | { 26 | l.PrintExpressionTree = PrintExpressionTree ? Console.Out : null; 27 | g.DoChunk(l.CompileChunk("\nNull(a, a);\n", "test.lua", Lua.StackTraceCompileOptions, new KeyValuePair("a", typeof(int))), 1); 28 | } 29 | catch (Exception e) 30 | { 31 | var d = LuaExceptionData.GetData(e); 32 | Assert.AreEqual(2, d[2].LineNumber); 33 | } 34 | } 35 | } // proc Exception01 36 | 37 | [TestMethod] 38 | public void Exception02() 39 | { 40 | using (var l = new Lua()) 41 | { 42 | var g = l.CreateEnvironment(); 43 | try 44 | { 45 | l.PrintExpressionTree = PrintExpressionTree ? Console.Out : null; 46 | g.DoChunk(l.CompileChunk("math.abs(-1 / a).A();", "test.lua", Lua.StackTraceCompileOptions, new KeyValuePair("a", typeof(int))), 1); 47 | } 48 | catch (Exception e) 49 | { 50 | var d = LuaExceptionData.GetData(e); 51 | Debug.Print("Error: {0}", e.Message); 52 | Debug.Print("Error at:\n{0}", d.StackTrace); 53 | Assert.AreEqual(1, d[2].LineNumber); // && d[2].ColumnNumber == 18 in release this is one 54 | } 55 | } 56 | } // proc Exception01 57 | 58 | private void ExceptionStackCore(LuaCompileOptions options) 59 | { 60 | using (var lua = new Lua()) 61 | { 62 | var g = lua.CreateEnvironment(); 63 | var chunk = lua.CompileChunk( 64 | Lines( 65 | "do", 66 | " error('test');", 67 | "end(function (e) return e; end);" 68 | ), 69 | "test.lua", options 70 | ); 71 | try 72 | { 73 | if (chunk.Run(g)[0] is LuaRuntimeException ex) 74 | { 75 | var data = LuaExceptionData.GetData(ex, true); 76 | Assert.AreEqual(2, data[3].LineNumber); 77 | } 78 | else 79 | Assert.Fail(); 80 | } 81 | catch (LuaRuntimeException) 82 | { 83 | Assert.Fail(); 84 | } 85 | } 86 | } 87 | 88 | [TestMethod] 89 | public void ExceptionStack01() 90 | => ExceptionStackCore(new LuaCompileOptions() { DebugEngine = LuaExceptionDebugger.Default }); 91 | 92 | [TestMethod] 93 | public void ExceptionStack02() 94 | => ExceptionStackCore(Lua.StackTraceCompileOptions); 95 | } // class Runtime 96 | } 97 | -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control01.lua: -------------------------------------------------------------------------------- 1 | local a = 2; 2 | if a < 2 then 3 | a = 1; 4 | elseif a > 2 then 5 | a = 2; 6 | else 7 | a = 3; 8 | end; 9 | return a; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control02.lua: -------------------------------------------------------------------------------- 1 | local a = 0; 2 | while a < 10 do 3 | a = a + 1; 4 | end; 5 | return a; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control03.lua: -------------------------------------------------------------------------------- 1 | local a = 0; 2 | repeat 3 | a = a + 1; 4 | until a >= 10; 5 | return a; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control04.lua: -------------------------------------------------------------------------------- 1 | local a = 0; 2 | while a < 10 do 3 | a = a + 1; 4 | if a == 4 then 5 | break; 6 | end; 7 | end; 8 | return a; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control05.lua: -------------------------------------------------------------------------------- 1 | local a = 0; 2 | ::start:: 3 | 4 | if a < 10 then 5 | a = a + 1; 6 | else 7 | goto ende; 8 | end; 9 | goto start; 10 | ::ende:: 11 | return a; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control06.lua: -------------------------------------------------------------------------------- 1 | local a = 0; 2 | for i = 1,10,1 do 3 | a = a + i; 4 | end; 5 | return a; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control08.lua: -------------------------------------------------------------------------------- 1 | local sum = 0; 2 | local t = { 1, 20, 300, 4000 } 3 | for i,v in ipairs(t) do 4 | sum = sum + v; 5 | end; 6 | return sum; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control09.lua: -------------------------------------------------------------------------------- 1 | local sum = 0; 2 | local t = { 1, 20, 300, 4000 } 3 | foreach c in t do 4 | sum = sum + c.Value; 5 | end; 6 | return sum; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control10.lua: -------------------------------------------------------------------------------- 1 | local sum = 0; 2 | for c in 3 | function(s, v) 4 | if v == 0 then 5 | return 1; 6 | elseif v == 1 then 7 | return 20; 8 | elseif v == 20 then 9 | return 300; 10 | elseif v == 300 then 11 | return 4000; 12 | else 13 | return nil; 14 | end; 15 | end, nil, 0 do 16 | 17 | sum = sum + c; 18 | end; 19 | return sum; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control11.lua: -------------------------------------------------------------------------------- 1 | local CompareMeClass = clr.LuaDLR.Test.ControlStructures.CompareMe; 2 | 3 | local a = CompareMeClass:ctor(1); 4 | local b = CompareMeClass:ctor(4); 5 | local c = 5; 6 | local d = 0; 7 | 8 | if a < b then 9 | d = d + 1; 10 | end; 11 | if c > a then 12 | d = d + 1; 13 | end; 14 | if a < c then 15 | d = d + 1; 16 | end; 17 | if a < 3 then 18 | d = d + 1; 19 | end; 20 | if 3 > a then 21 | d = d + 1; 22 | end; 23 | if "a" < "b" then 24 | d = d + 1; 25 | end; 26 | return d; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control12.lua: -------------------------------------------------------------------------------- 1 | local CompareMeClass = clr.LuaDLR.Test.ControlStructures.CompareMe; 2 | 3 | local a = CompareMeClass:ctor(1); 4 | return a + 3; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control19.lua: -------------------------------------------------------------------------------- 1 | local i : int = 0; 2 | repeat 3 | local l : string; 4 | if i < 3 then 5 | l = "test " .. i; 6 | else 7 | l = nil; 8 | end; 9 | print(l); 10 | i = i + 1; 11 | until l == nil; 12 | return i; 13 | -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Control20.lua: -------------------------------------------------------------------------------- 1 | local t = {}; 2 | local j = 1; 3 | for i = 500000500000, 500000500001 do 4 | print(tostring(i)); 5 | t[j] = i; 6 | j = j + 1; 7 | end; 8 | return t[1], t[2]; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Coroutines01.lua: -------------------------------------------------------------------------------- 1 | function foo (a) 2 | print("foo", a) 3 | return coroutine.yield(2*a) 4 | end 5 | 6 | co = coroutine.create(function (a,b) 7 | print("co-body", a, b) 8 | local r = foo(a+1) 9 | print("co-body", r) 10 | local r, s = coroutine.yield(a+b, a-b) 11 | print("co-body", r, s) 12 | return b, "end" 13 | end) 14 | 15 | print("main", coroutine.resume(co, 1, 10)) 16 | print("main", coroutine.resume(co, "r")) 17 | print("main", coroutine.resume(co, "x", "y")) 18 | print("main", coroutine.resume(co, "x", "y")) -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Echo.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo This text goes to Standard Output 3 | echo. 4 | echo Line 5 | echo This text goes to Standard Error 1>&2 -------------------------------------------------------------------------------- /NeoLua.Test/Lua/EnvDynamicCall01.lua: -------------------------------------------------------------------------------- 1 | local l = { 2 | add = 100, 3 | 4 | a = function(a) 5 | return a * 4; 6 | end, 7 | 8 | c = function(self, a) 9 | return self.add + a * 2; 10 | end 11 | }; 12 | 13 | function l:b(a) 14 | return self.add + a * 3 15 | end; 16 | 17 | function test(a) 18 | return a * 2; 19 | end; 20 | 21 | b = l; 22 | -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Function08.lua: -------------------------------------------------------------------------------- 1 | local function a() 2 | local i = 1; 3 | local t = function() 4 | i = i + 1; 5 | return i; 6 | end; 7 | return i, t; 8 | end; 9 | 10 | local i, b = a(); 11 | b(); 12 | b(); 13 | 14 | return i, b(); -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Function08a.lua: -------------------------------------------------------------------------------- 1 | local function a() 2 | local i : int = 1; 3 | local t = function() : int 4 | i = i + 1; 5 | return i; 6 | end; 7 | return i, t; 8 | end; 9 | 10 | local i : int, b = a(); 11 | b(); 12 | b(); 13 | 14 | return i, b(); -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Generics01.lua: -------------------------------------------------------------------------------- 1 | local lst = clr.System.Collections.Generic.List[clr.System.Object](); 2 | 3 | lst:Add(1); 4 | lst:Add(2); 5 | lst:Add("String"); 6 | 7 | print("Enum:"); 8 | foreach a in lst do 9 | print(a); 10 | end; 11 | 12 | print("Index:"); 13 | for i = 0,lst.Count-1,1 do 14 | print(i .. ": " .. lst[i]); 15 | end; 16 | 17 | return lst.Count; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Runtime11.lua: -------------------------------------------------------------------------------- 1 | local s = "hello world from Lua 6" 2 | local i = 0; 3 | local t = ""; 4 | for w in string.gmatch(s, "%a+") do 5 | print(w); 6 | i = i + 1; 7 | t = t .. w; 8 | end; 9 | return i, t; -------------------------------------------------------------------------------- /NeoLua.Test/Lua/Runtime12.lua: -------------------------------------------------------------------------------- 1 | local s = "from=world, to=Lua" 2 | local i = 0; 3 | local t = ""; 4 | for k, v in string.gmatch(s, "(%w+)=(%w+)") do 5 | print(k .. "=" .. v); 6 | i = i + 1; 7 | t = t .. k .. v; 8 | end; 9 | return i, t; -------------------------------------------------------------------------------- /NeoLua.Test/LuaEmitTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Dynamic; 3 | using System.Linq; 4 | using System.Linq.Expressions; 5 | using System.Reflection; 6 | 7 | using Microsoft.VisualStudio.TestTools.UnitTesting; 8 | using Neo.IronLua; 9 | 10 | namespace LuaDLR.Test 11 | { 12 | [TestClass] 13 | public class LuaEmitTests 14 | { 15 | private LuaType LuaTypeString = LuaType.GetType(typeof(string)); 16 | 17 | [TestMethod] 18 | public void FindMember_StringJoin_WithLuaResultMatchesObjectArrayOverload() 19 | { 20 | var arguments = GetDynamicMetaObjectArguments(" ", new LuaResult("Hello", "World", "!!")); 21 | TestMethodInfoForArguments(typeof(string), nameof(string.Join), arguments, new[] { typeof(string), typeof(object[]) }); 22 | } 23 | 24 | [TestMethod] 25 | public void FindMember_StringStringFormat_WithStringObj() 26 | { 27 | var arguments = GetDynamicMetaObjectArguments("Hello {0}", "World"); 28 | TestMethodInfoForArguments(typeof(string), nameof(string.Format), arguments, new[] { typeof(string), typeof(object) }); 29 | } 30 | 31 | [TestMethod] 32 | public void FindMember_StringStringFormat_WithStringObjArray() 33 | { 34 | var arguments = GetDynamicMetaObjectArguments("Hello {0}{1}", new object[] { "World", "!!" }); 35 | TestMethodInfoForArguments(typeof(string), nameof(string.Format), arguments, new[] { typeof(string), typeof(object[]) }); 36 | } 37 | 38 | [TestMethod] 39 | public void FindMember_StringConcat_WithStringsAndLuaResultMatchesObjectArrayOverload() 40 | { 41 | var arguments = GetDynamicMetaObjectArguments("Test", ":", new LuaResult("Hello", "World", "!!")); 42 | TestMethodInfoForArguments(typeof(string), nameof(string.Concat), arguments, new[] { typeof(object[]) }); 43 | } 44 | 45 | [TestMethod] 46 | public void FindMember_LuaResultGSub() 47 | { 48 | var arguments = GetDynamicMetaObjectArguments("abc", "a", "b"); 49 | TestMethodInfoForArguments(typeof(LuaLibraryString), nameof(LuaLibraryString.gsub), arguments, new[] { typeof(string) , typeof(string) , typeof(object), typeof(int) }); 50 | } 51 | 52 | 53 | [TestMethod] 54 | public void FindMember_ParamArrayWithNoArg() 55 | { 56 | var arguments = GetDynamicMetaObjectArguments(); 57 | TestMethodInfoForArguments(typeof(LuaFile), nameof(LuaFile.write), arguments, new[] { typeof(object[]) }); 58 | } 59 | 60 | [TestMethod] 61 | public void FindMember_ParamArrayWithSingleArg() 62 | { 63 | var arguments = GetDynamicMetaObjectArguments("Hello World"); 64 | TestMethodInfoForArguments(typeof(LuaFile), nameof(LuaFile.write), arguments, new[] { typeof(object[]) }); 65 | } 66 | 67 | [TestMethod] 68 | public void FindMember_ParamArrayWithMultipleArgs() 69 | { 70 | var arguments = GetDynamicMetaObjectArguments("Hello World", "Some more", "and another"); 71 | TestMethodInfoForArguments(typeof(LuaFile), nameof(LuaFile.write), arguments, new[] { typeof(object[]) }); 72 | } 73 | 74 | void TestMethodInfoForArguments(Type type, string memberName, DynamicMetaObject[] arguments, Type[] argumentTypesForExpectedOverload) 75 | { 76 | var methodAlternatives = type.GetMember(memberName).Cast().ToArray(); 77 | var callInfo = new CallInfo(arguments.Length); 78 | var methodInfo = LuaEmit.FindMember(methodAlternatives, callInfo, arguments, GetArgumentType, false); 79 | Assert.IsNotNull(methodInfo, $"Found no valid overload for {type.Name}:{memberName}"); 80 | var expected = type.GetMethod(memberName, argumentTypesForExpectedOverload); 81 | Assert.AreEqual(expected, methodInfo); 82 | } 83 | 84 | static Type GetArgumentType(DynamicMetaObject obj) => obj.LimitType; 85 | 86 | DynamicMetaObject[] GetDynamicMetaObjectArguments(params object[] arguments) 87 | { 88 | DynamicMetaObject[] res = new DynamicMetaObject[arguments.Length]; 89 | for (int i = 0; i < arguments.Length; i++) 90 | { 91 | object argument = arguments[i]; 92 | var name = $"$arg{i + 1}"; 93 | res[i] = CreateMetaObjectParameter(name, argument); 94 | } 95 | 96 | return res; 97 | } 98 | 99 | DynamicMetaObject CreateMetaObjectParameter(string name, object value) 100 | { 101 | var type = value is string ? LuaTypeString : value.GetType(); 102 | return DynamicMetaObject.Create(value, Expression.Parameter(type, name)); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /NeoLua.Test/LuaLibs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using Microsoft.VisualStudio.TestTools.UnitTesting; 10 | using Neo.IronLua; 11 | 12 | namespace LuaDLR.Test 13 | { 14 | [TestClass] 15 | public class LuaLibs : TestHelper 16 | { 17 | [TestMethod] 18 | public void TestExecute01() 19 | { 20 | TestCode("return os.execute('dir c:\')", true, "exit", 0); 21 | } 22 | 23 | [TestMethod] 24 | public void TestExecute02() 25 | { 26 | TestCode("return os.execute('\"cmd.exe\" /c dir c:\')", true, "exit", 0); 27 | } 28 | [TestMethod] 29 | public void TestExecute03() 30 | { 31 | string sBatch = Path.Combine(Path.GetDirectoryName(typeof(LuaLibs).Assembly.Location), "Lua", "Echo.bat"); 32 | ProcessStartInfo psi = new ProcessStartInfo(Path.Combine(Environment.SystemDirectory, "cmd.exe"), "/c " + sBatch + " 2>&1"); 33 | psi.RedirectStandardOutput = true; 34 | psi.UseShellExecute = false; 35 | psi.CreateNoWindow = true; 36 | using (Process p = Process.Start(psi)) 37 | { 38 | string sLine; 39 | while ((sLine = p.StandardOutput.ReadLine()) != null) 40 | Debug.Print(sLine); 41 | 42 | Debug.Print("ExitCode: {0}", p.ExitCode); 43 | } 44 | } 45 | 46 | private static string GetEchoBatch() 47 | { 48 | var f = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(typeof(LuaLibs).Assembly.Location), "..\\..\\..\\Lua", "Echo.bat")); 49 | return File.Exists(f) 50 | ? f 51 | : throw new FileNotFoundException("Batch file missing.", f); 52 | } // func GetEchoBatch 53 | 54 | private const string echoOutput = "\nThis text goes to Standard Output\n\nLine"; 55 | 56 | [TestMethod] 57 | public void TestExecute04() 58 | { 59 | TestCode(Lines( 60 | String.Format("do (f = io.popen([[{0}]], 'r+'))", GetEchoBatch()), 61 | " local s = '';", 62 | " while true do", 63 | " local l = f:read();", 64 | " if l ~= nil then", 65 | " s = s .. '\\n' .. l;", 66 | " else", 67 | " break;", 68 | " end;", 69 | " end;", 70 | " return f:close(), s", 71 | "end;" 72 | ), 0, echoOutput); 73 | } 74 | 75 | [TestMethod] 76 | public void TestExecute05() 77 | { 78 | TestCode(Lines( 79 | String.Format("do (f = io.popen([[{0}]], 'r+'))", GetEchoBatch()), 80 | " local s = '';", 81 | " for l in f:lines() do", 82 | " s = s .. '\\n' .. l;", 83 | " end;", 84 | " return f:close(), s", 85 | "end;" 86 | ), 0, echoOutput); 87 | } 88 | 89 | [TestMethod] 90 | public void TestRegEx01() 91 | { 92 | TestCode( 93 | Lines( 94 | "s = [[", 95 | "(Standard)", 96 | "(() Double Brackets ())", 97 | "( Across Lines", 98 | ")", 99 | "(() Double Brackets Across Lines", 100 | "())", 101 | "(2 in) (A Line)", 102 | "Before(Inside)After", 103 | "MissMatch (found))", 104 | ")Not Matched(", 105 | "MissMatch2 ((found2)", 106 | "]]", 107 | "local t = '';", 108 | "for k in string.gmatch(s,'%b()') do", 109 | " print(k)", 110 | " t = t .. k .. '\\n'", 111 | "end", 112 | "return t" 113 | ), 114 | String.Join("\n", 115 | "(Standard)", 116 | "(() Double Brackets ())", 117 | "( Across Lines", 118 | ")", 119 | "(() Double Brackets Across Lines", 120 | "())", 121 | "(2 in)", 122 | "(A Line)", 123 | "(Inside)", 124 | "(found)", 125 | "(found2)", 126 | "" 127 | ) 128 | ); 129 | } 130 | 131 | [TestMethod] 132 | public void TestFind01() 133 | { 134 | TestCode("return string.find('fsdfsdF/R/1/EP', '.*/.*/.*/.*')", 1, 14); 135 | } 136 | 137 | [TestMethod] 138 | public void TestFind02() 139 | { 140 | TestCode("return string.find('fsdfsdF/R/1/EP', '.*/.*/.*/(.*)')", 1, 14, "EP"); 141 | } 142 | 143 | [TestMethod] 144 | public void TestFind03() 145 | { 146 | TestCode("return string.find('fsdfsdF/R/1/EP', '.*/(.*)/.*/(.*)')", 1, 14, "R", "EP"); 147 | } 148 | 149 | [TestMethod] 150 | public void TestFind04() 151 | { 152 | TestCode("return string.find(' abc', '%a+');", 4, 6); 153 | } // proc TestRuntimeLua13 154 | 155 | [TestMethod] 156 | public void TestMatch01() 157 | { 158 | TestCode("return string.match('(abc=123)', '%(([%s%a%d%-,=%_]*)');", "abc=123"); 159 | } // proc TestRuntimeLua13 160 | 161 | [TestMethod] 162 | public void TestLoad01() 163 | { 164 | TestCode(Lines( 165 | //"local fn = function(...) local a, b = ...; return a, b; end;", 166 | "local fn = load('local a, b = ...; return a, b;');", 167 | "return fn(23,42);"), 168 | 23, 42 169 | ); 170 | } 171 | 172 | [TestMethod] 173 | public void TestRequire01() 174 | { 175 | // Lua should find a module by replacing '?' with the module name in the package path. 176 | Directory.CreateDirectory("lua_module"); 177 | File.WriteAllText(Path.Combine("lua_module", "ReqModule.lua"), "function foo() return 'bar' end"); 178 | 179 | TestCode(Lines( 180 | "package.path = package.path..';./lua_module/?.lua'", 181 | "require('ReqModule');", 182 | "return foo();"), 183 | "bar" 184 | ); 185 | } 186 | 187 | [TestMethod] 188 | public void TestRequire02() 189 | { 190 | // Lua should find a module by searching for the module in package path directories 191 | Directory.CreateDirectory("lua_module"); 192 | File.WriteAllText(Path.Combine("lua_module", "ReqModule.lua"), "function foo() return 'bar' end"); 193 | 194 | TestCode(Lines( 195 | "package.path = package.path..';./lua_module'", 196 | "require('ReqModule');", 197 | "return foo();"), 198 | "bar" 199 | ); 200 | } 201 | 202 | [TestMethod] 203 | public void TestRequire03() 204 | { 205 | // Lua should find a module by replacing '?' with the module name in the environment LUA_PATH. 206 | Directory.CreateDirectory("lua_module"); 207 | File.WriteAllText(Path.Combine("lua_module", "ReqModule.lua"), "function foo() return 'bar' end"); 208 | Environment.SetEnvironmentVariable("LUA_PATH", "./lua_module/?.lua"); 209 | TestCode(Lines( 210 | 211 | "require('ReqModule');", 212 | "return foo();"), 213 | "bar" 214 | ); 215 | } 216 | 217 | [DataTestMethod] 218 | [DataRow("%a", "\\p{L}")] 219 | [DataRow("%%", "%")] 220 | [DataRow("%_", "_")] 221 | [DataRow("%(([%s%a%d%-,=%_]*)", @"\(([\s\p{L}\d\-,=_]*)")] 222 | public void CanTranslatesRegularExpression(string from, string to) 223 | { 224 | var (translatedPattern, _) = LuaLibraryString.TranslateRegularExpression(from); 225 | Assert.AreEqual(to, translatedPattern); 226 | // ensure it parses 227 | var re = new Regex(translatedPattern); 228 | } 229 | 230 | 231 | [DataTestMethod] 232 | [DataRow("kt foobar win64 ", "(kt)%s+(foobar[a-zA-Z]*)%s+([%a%d_]+)%s+", 2, "win64")] 233 | [DataRow("kt foobar win64 LKG_AutoPlayer_Tests:Autoplayer_", "(kt)%s+(foobar[a-zA-Z]*)%s+([%a%d_]+)%s+", 2, "win64")] 234 | // 235 | public void CanMatchRegularExpression(string line, string pattern, int resultIndex, string expected) 236 | { 237 | var res = LuaLibraryString.match(line, pattern); 238 | Assert.AreEqual(expected, res[resultIndex]); 239 | } 240 | } 241 | } -------------------------------------------------------------------------------- /NeoLua.Test/NeoLua.Test.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net48 5 | true 6 | NeoLua.snk 7 | LuaDLR.Test 8 | LuaDLR.Test 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /NeoLua.Test/NeoLua.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoLua.Test/NeoLua.snk -------------------------------------------------------------------------------- /NeoLua.Test/RunLuaTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using Microsoft.VisualStudio.TestTools.UnitTesting; 9 | using Neo.IronLua; 10 | 11 | namespace LuaDLR.Test 12 | { 13 | [TestClass] 14 | public class RunLuaTests : TestHelper 15 | { 16 | private object TestAssert(object test, string sMessage) 17 | { 18 | if (!(bool)Lua.RtConvertValue(test, typeof(bool))) 19 | { 20 | LuaStackFrame frame = LuaExceptionData.GetStackTrace(new StackTrace(0, true)).FirstOrDefault(c => c.Type == LuaStackFrameType.Lua); 21 | if (frame == null) 22 | Assert.IsTrue(false, "Test failed (unknown position) " + sMessage); 23 | else 24 | Assert.IsTrue(false, "Test failed at line {0}, column {1}, file {2} {3}", frame.LineNumber, frame.ColumnNumber, frame.FileName, sMessage); 25 | } 26 | return test; 27 | } 28 | 29 | private void DoScript(Lua l, LuaGlobal g, string sScript) 30 | { 31 | Type type = typeof(RunLuaTests); 32 | using (Stream src = type.Assembly.GetManifestResourceStream(type, "CompTests." + sScript)) 33 | using (StreamReader sr = new StreamReader(src)) 34 | { 35 | Console.WriteLine(); 36 | Console.WriteLine(new string('=', 60)); 37 | Console.WriteLine("= " + sScript); 38 | Console.WriteLine(); 39 | try 40 | { 41 | g.DoChunk(l.CompileChunk(sr, sScript, Lua.StackTraceCompileOptions)); 42 | } 43 | catch (Exception e) 44 | { 45 | if (e is LuaException) 46 | Console.WriteLine("Line: {0}, Column: {1}", ((LuaException)e).Line, ((LuaException)e).Column); 47 | Console.WriteLine("StackTrace:"); 48 | Console.WriteLine(LuaExceptionData.GetData(e).StackTrace); 49 | throw; 50 | } 51 | } 52 | } 53 | 54 | [TestMethod] 55 | public void RunTest() 56 | { 57 | using (Lua l = new Lua()) 58 | { 59 | var g = l.CreateEnvironment(); 60 | dynamic dg = g; 61 | 62 | dg.math.randomseed(0); 63 | dg.assert = new Func(TestAssert); 64 | 65 | DoScript(l, g, "calls.lua"); 66 | DoScript(l, g, "strings.lua"); 67 | //DoScript(l, g, "literals.lua"); 68 | 69 | DoScript(l, g, "math.lua"); 70 | DoScript(l, g, "bitwise.lua"); 71 | } 72 | } 73 | 74 | [TestMethod] 75 | public void TestSingle01() 76 | { 77 | TestCode("return 0xfffffffffffff800", 0xfffffffffffff800); 78 | } 79 | 80 | [TestMethod] 81 | public void TestSingle02() 82 | { 83 | TestCode(Lines( 84 | "function deep(n)", 85 | " if n > 0 then return deep(n-1); else return 101; end;", 86 | "end;", 87 | "return deep(3000);"), 101); 88 | } 89 | 90 | [TestMethod] 91 | public void TestSingle03() 92 | { 93 | TestCode("a = nil; (function (x) a = x end)(23) return a", 23); 94 | } 95 | 96 | [TestMethod] 97 | public void TestSingle04() 98 | { 99 | TestCode(Lines( 100 | "local x = \"-- a comment\0\0\0\\n x = 10 + \\n23; \\", 101 | " local a = function () x = 'hi' end; \\", 102 | " return '\\0'\"", 103 | "function read1 (x)", 104 | " local i = 0", 105 | " return function ()", 106 | " collectgarbage()", 107 | " i=i+1", 108 | " return string.sub(x, i, i)", 109 | " end", 110 | "end", 111 | "a = assert(load(read1(x), 'modname', 't', _G))", 112 | "return a(), _G.x;" 113 | ), "\0", 33); 114 | } 115 | 116 | [TestMethod] 117 | public void TestSingle05() 118 | { 119 | TestCode("return tonumber('0ffffFFFF', 16) + 1", (long)4294967296); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /NeoLua.Test/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | using Neo.IronLua; 7 | 8 | namespace LuaDLR.Test 9 | { 10 | public class TestHelper 11 | { 12 | public static bool PrintExpressionTree = true; 13 | 14 | public string Lines(params string[] lines) 15 | => String.Join(Environment.NewLine, lines); 16 | 17 | public string GetLines(string name) 18 | { 19 | using (var src = typeof(TestHelper).Assembly.GetManifestResourceStream(typeof(TestHelper), name)) 20 | using (var tr = new StreamReader(src)) 21 | return tr.ReadToEnd(); 22 | } // func GetLines 23 | 24 | public void TestCode(string code, params object[] expectedResult) 25 | { 26 | using (var l = new Lua()) 27 | { 28 | l.PrintExpressionTree = PrintExpressionTree ? Console.Out : null; 29 | var g = l.CreateEnvironment(); 30 | Console.WriteLine("Test: {0}", code); 31 | Console.WriteLine(new string('=', 66)); 32 | var sw = new Stopwatch(); 33 | sw.Start(); 34 | TestResult(g.DoChunk(code, "test.lua"), expectedResult); 35 | Console.WriteLine(" Dauer: {0}ms", sw.ElapsedMilliseconds); 36 | Console.WriteLine(); 37 | Console.WriteLine(); 38 | } 39 | } // proc TestCode 40 | 41 | public void TestExpr(string expression, params object[] expectedResult) 42 | => TestCode("return " + expression + ";", expectedResult); 43 | 44 | private static string FormatValue(object v) 45 | => $"({(v == null ? "object" : v.GetType().Name)}){v}"; 46 | 47 | public static void TestResult(LuaResult result, params object[] expectedResult) 48 | { 49 | if (result == null) 50 | throw new ArgumentNullException("no result"); 51 | 52 | if (expectedResult == null || expectedResult.Length == 0) // no results expected 53 | { 54 | if (result.Values.Length == 0) 55 | { 56 | Console.WriteLine("OK: no result == no result"); 57 | } 58 | else 59 | { 60 | var msg = $"FAIL: no result != {FormatValue(result[0])}"; 61 | Console.WriteLine(msg); 62 | Assert.Fail(msg); 63 | } 64 | } 65 | else 66 | { 67 | for (var i = 0; i < expectedResult.Length; i++) 68 | { 69 | var valueResult = result[i]; 70 | var valueExpected = expectedResult[i]; 71 | 72 | if (valueResult is double) 73 | valueResult = Math.Round((double)valueResult, 3); 74 | if (valueExpected is double) 75 | valueExpected = Math.Round((double)valueExpected, 3); 76 | 77 | if (valueResult is LuaTable && valueExpected is KeyValuePair[]) 78 | TestTable((LuaTable)valueResult, (KeyValuePair[])valueExpected); 79 | else 80 | { 81 | var isOk = Equals(valueResult, valueExpected); 82 | var msg = $"{(isOk ? "OK" : "FAIL")}: {FormatValue(valueResult)} {(isOk ? "==" : "!=")} {FormatValue(valueExpected)}"; 83 | Console.WriteLine(msg); 84 | if (!isOk) 85 | Assert.Fail(msg); 86 | } 87 | } 88 | if (result.Values.Length != expectedResult.Length) 89 | { 90 | var format = $"FAIL: Result Count {result.Values.Length} != {expectedResult.Length}"; 91 | Console.WriteLine(format); 92 | Assert.Fail(format); 93 | } 94 | } 95 | } // proc TestResult 96 | 97 | public static void TestTable(LuaTable table, KeyValuePair[] tvs) 98 | { 99 | var failed = false; 100 | Console.WriteLine("Table {"); 101 | TestTable(" ", table, tvs, ref failed); 102 | Console.WriteLine("}"); 103 | Assert.IsFalse(failed); 104 | } // proc TestTable 105 | 106 | private static void TestTable(string sIndent, LuaTable table, KeyValuePair[] tvs, ref bool failed) 107 | { 108 | var isTested = new bool[tvs.Length]; 109 | Array.Clear(isTested, 0, isTested.Length); 110 | 111 | foreach (var tv in table) 112 | { 113 | if (String.Compare(tv.Key as string, LuaTable.csMetaTable) == 0) 114 | continue; 115 | 116 | var idx = Array.FindIndex(tvs, c => Object.Equals(tv.Key, c.Key)); 117 | if (idx == -1) 118 | { 119 | Console.WriteLine(sIndent + "Key not found: {0}", FormatValue(tv.Key)); 120 | failed |= true; 121 | } 122 | else 123 | { 124 | if (tv.Value is LuaTable && tvs[idx].Value is KeyValuePair[]) 125 | { 126 | Console.WriteLine(sIndent + "Table[{0}] {{", FormatValue(tv.Key)); 127 | TestTable(sIndent + " ", (LuaTable)tv.Value, (KeyValuePair[])(tvs[idx].Value), ref failed); 128 | Console.WriteLine(sIndent + "}"); 129 | } 130 | else 131 | { 132 | var lOk = Object.Equals(tvs[idx].Value, tv.Value); 133 | Console.WriteLine(sIndent + "[{0}]: {1} {2} {3}", FormatValue(tv.Key), FormatValue(tv.Value), lOk ? "==" : "!=", FormatValue(tvs[idx].Value)); 134 | failed |= !lOk; 135 | } 136 | isTested[idx] = true; 137 | } 138 | } 139 | 140 | for (var i = 0; i < isTested.Length; i++) 141 | { 142 | if (!isTested[i]) 143 | { 144 | Console.WriteLine(sIndent + " Key not tested: {0}", FormatValue(tvs[i].Key)); 145 | failed |= true; 146 | } 147 | } 148 | } // proc TestTable 149 | 150 | public static KeyValuePair[] Table(params KeyValuePair[] tv) 151 | => tv; 152 | 153 | public static KeyValuePair TV(object item, object value) 154 | => new KeyValuePair(item, value); 155 | 156 | public object[] NullResult => new object[] { null }; 157 | } // class TestHelper 158 | } 159 | -------------------------------------------------------------------------------- /NeoLua/Extern/printf.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoLua/Extern/printf.cs -------------------------------------------------------------------------------- /NeoLua/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 |  2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.close~Neo.IronLua.LuaResult")] 8 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.flush")] 9 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.lines(System.Object[])~Neo.IronLua.LuaResult")] 10 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.read(System.Object[])~Neo.IronLua.LuaResult")] 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.write(System.Object[])~Neo.IronLua.LuaResult")] 12 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.seek(System.String,System.Int64)~Neo.IronLua.LuaResult")] 13 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaFile.setvbuf(System.String,System.Int32)")] 14 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaThread.create(System.Object)~Neo.IronLua.LuaThread")] 15 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaThread.resume(System.Object[])~Neo.IronLua.LuaResult")] 16 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaThread.resume(Neo.IronLua.LuaThread,System.Object[])~Neo.IronLua.LuaResult")] 17 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaThread.yield(System.Object[])~Neo.IronLua.LuaResult")] 18 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaThread.running~Neo.IronLua.LuaResult")] 19 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:Neo.IronLua.LuaThread.status(System.Object)~Neo.IronLua.LuaResult")] 20 | 21 | -------------------------------------------------------------------------------- /NeoLua/LuaChunk.cs: -------------------------------------------------------------------------------- 1 | #region -- copyright -- 2 | // 3 | // Licensed to the Apache Software Foundation (ASF) under one 4 | // or more contributor license agreements. See the NOTICE file 5 | // distributed with this work for additional information 6 | // regarding copyright ownership. The ASF licenses this file 7 | // to you under the Apache License, Version 2.0 (the 8 | // "License"); you may not use this file except in compliance 9 | // with the License. You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, 14 | // software distributed under the License is distributed on an 15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. See the License for the 17 | // specific language governing permissions and limitations 18 | // under the License. 19 | // 20 | #endregion 21 | using System; 22 | using System.Reflection; 23 | 24 | namespace Neo.IronLua 25 | { 26 | #region -- class LuaChunk --------------------------------------------------------- 27 | 28 | /// Represents the compiled chunk. 29 | public class LuaChunk 30 | { 31 | private readonly Lua lua; 32 | private readonly string name; 33 | private Delegate chunk = null; 34 | 35 | /// Create the chunk 36 | /// Attached runtime 37 | /// Name of the chunk 38 | /// 39 | protected internal LuaChunk(Lua lua, string name, Delegate chunk) 40 | { 41 | this.lua = lua; 42 | this.name = name; 43 | this.chunk = chunk; 44 | } // ctor 45 | 46 | /// Assign a methodname with the current chunk. 47 | /// unique method name 48 | protected void RegisterMethod(string name) 49 | => Lua.RegisterMethod(name, this); 50 | 51 | /// Gets for the StackFrame the position in the source file. 52 | /// 53 | /// 54 | /// 55 | protected internal virtual ILuaDebugInfo GetDebugInfo(MethodBase method, int ilOffset) 56 | => null; 57 | 58 | /// Executes the Chunk on the given Environment 59 | /// 60 | /// 61 | /// 62 | public LuaResult Run(LuaTable env, params object[] callArgs) 63 | { 64 | if (!IsCompiled) 65 | throw new ArgumentException(Properties.Resources.rsChunkNotCompiled, "chunk"); 66 | 67 | var args = new object[callArgs == null ? 1 : callArgs.Length + 1]; 68 | args[0] = env; 69 | if (callArgs != null) 70 | Array.Copy(callArgs, 0, args, 1, callArgs.Length); 71 | 72 | try 73 | { 74 | var r = chunk.DynamicInvoke(args); 75 | return r is LuaResult ? (LuaResult)r : new LuaResult(r); 76 | } 77 | catch (TargetInvocationException e) 78 | { 79 | throw e.InnerException; // rethrow with new stackstrace 80 | } 81 | } // proc Run 82 | 83 | /// Returns the associated LuaEngine 84 | public Lua Lua => lua; 85 | /// Set or get the compiled script. 86 | protected internal Delegate Chunk { get => chunk; set => chunk = value; } 87 | 88 | /// Name of the compiled chunk. 89 | public string ChunkName => name; 90 | 91 | /// Is the chunk compiled and executable. 92 | public bool IsCompiled => chunk != null; 93 | /// Is the chunk compiled with debug infos 94 | public virtual bool HasDebugInfo => false; 95 | 96 | /// Returns the declaration of the compiled chunk. 97 | public MethodInfo Method => chunk?.GetMethodInfo(); 98 | 99 | /// Get the IL-Size 100 | public virtual int Size 101 | { 102 | get 103 | { 104 | if (chunk == null) 105 | return 0; 106 | 107 | // Gib den Type zurück 108 | var miChunk = chunk.GetMethodInfo(); 109 | var typeMethod = miChunk.GetType(); 110 | if (typeMethod == RuntimeMethodInfoType) 111 | { 112 | dynamic methodBody = ((dynamic)miChunk).GetMethodBody(); 113 | return methodBody.GetILAsByteArray().Length; 114 | } 115 | else if (typeMethod == RtDynamicMethodType) 116 | { 117 | dynamic dynamicMethod = RtDynamicMethodOwnerFieldInfo.GetValue(miChunk); 118 | if (dynamicMethod == null) 119 | return -1; 120 | return dynamicMethod.GetILGenerator().ILOffset; 121 | } 122 | else 123 | return -1; 124 | } 125 | } // prop Size 126 | 127 | // -- Static -------------------------------------------------------------- 128 | 129 | #pragma warning disable IDE1006 // Naming Styles 130 | private static readonly Type RuntimeMethodInfoType = Type.GetType("System.Reflection.RuntimeMethodInfo"); 131 | private static readonly Type DynamicMethodType = Type.GetType("System.Reflection.Emit.DynamicMethod"); 132 | private static readonly Type RtDynamicMethodType = Type.GetType("System.Reflection.Emit.DynamicMethod+RTDynamicMethod"); 133 | private static readonly FieldInfo RtDynamicMethodOwnerFieldInfo; 134 | #pragma warning restore IDE1006 // Naming Styles 135 | 136 | static LuaChunk() 137 | { 138 | if (RtDynamicMethodType != null) 139 | { 140 | RtDynamicMethodOwnerFieldInfo = RtDynamicMethodType.GetTypeInfo().FindDeclaredField("m_owner", ReflectionFlag.NonPublic); 141 | if (RtDynamicMethodOwnerFieldInfo == null) 142 | throw new InvalidOperationException("RTDynamicMethod:m_owner not found"); 143 | } 144 | else 145 | { 146 | RtDynamicMethodOwnerFieldInfo = null; 147 | } 148 | } // sctor 149 | } // class LuaChunk 150 | 151 | #endregion 152 | } 153 | -------------------------------------------------------------------------------- /NeoLua/NeoLua.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Neo.Lua 5 | Neo.IronLua 6 | net451;net48;netstandard2.0;net6.0 7 | true 8 | A Lua implementation for the Dynamic Language Runtime (DLR). 9 | NeoLua 10 | A Lua implementation for the Dynamic Language Runtime (DLR). 11 | 12 | NeoLua is an implementation of the Lua language. Currently the implementation is on the level of Lua 13 | 5.3 http://www.lua.org/manual/5.3/manual.html). The goal is to match the reference of the C-Lua implementation and combine this with full .net framework support. 14 | 15 | NeoLua is implemented in C# and uses the Dynamic Language Runtime. It therefore integrates very well with the .net framework. 16 | 17 | This library contains the desktop parts of the lua implementation. 18 | Lua C# .net DLR Dynamic Language 19 | 20 | true 21 | NeoLua.snk 22 | disable 23 | 9 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | True 38 | True 39 | Resources.resx 40 | 41 | 42 | 43 | 44 | ResXFileCodeGenerator 45 | Resources.Designer.cs 46 | 47 | 48 | -------------------------------------------------------------------------------- /NeoLua/NeoLua.licenseheader: -------------------------------------------------------------------------------- 1 | extensions: designer.cs generated.cs 2 | extensions: .cs 3 | #region -- copyright -- 4 | // 5 | // Licensed to the Apache Software Foundation (ASF) under one 6 | // or more contributor license agreements. See the NOTICE file 7 | // distributed with this work for additional information 8 | // regarding copyright ownership. The ASF licenses this file 9 | // to you under the Apache License, Version 2.0 (the 10 | // "License"); you may not use this file except in compliance 11 | // with the License. You may obtain a copy of the License at 12 | // 13 | // http://www.apache.org/licenses/LICENSE-2.0 14 | // 15 | // Unless required by applicable law or agreed to in writing, 16 | // software distributed under the License is distributed on an 17 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 | // KIND, either express or implied. See the License for the 19 | // specific language governing permissions and limitations 20 | // under the License. 21 | // 22 | #endregion 23 | extensions: .vb 24 | #Region "-- copyright --" 25 | ' 26 | ' Licensed to the Apache Software Foundation (ASF) under one 27 | ' or more contributor license agreements. See the NOTICE file 28 | ' distributed with this work for additional information 29 | ' regarding copyright ownership. The ASF licenses this file 30 | ' to you under the Apache License, Version 2.0 (the 31 | ' "License"); you may not use this file except in compliance 32 | ' with the License. You may obtain a copy of the License at 33 | ' 34 | ' http://www.apache.org/licenses/LICENSE-2.0 35 | ' 36 | ' Unless required by applicable law or agreed to in writing, 37 | ' software distributed under the License is distributed on an 38 | ' "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 39 | ' KIND, either express or implied. See the License for the 40 | ' specific language governing permissions and limitations 41 | ' under the License. 42 | ' 43 | #End Region -------------------------------------------------------------------------------- /NeoLua/NeoLua.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoLua/NeoLua.snk -------------------------------------------------------------------------------- /NeoLua/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | 6 | 7 | [assembly: ComVisible(false)] 8 | [assembly: Guid("8278b1f1-cfc2-41e2-94c1-5167abbce780")] 9 | 10 | [assembly: InternalsVisibleTo("LuaDLR.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f94d9d7c92e0848eab4f6ef97934d020c24bbc122b915b00789af183f3e3084dc4a0811754a5308c803d25cd14dd42eee792a84295432dd781995fb270bd29ae90b431e8f74d56ea32bc80955ae81a52e5cacf6834da0ae4f9c805b436f3b562e415326da8b3a4df94e67b4e737b269d4277a03fe45a8f54cf8bc889f60848ea")] 11 | [assembly: InternalsVisibleTo("lua.dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f94d9d7c92e0848eab4f6ef97934d020c24bbc122b915b00789af183f3e3084dc4a0811754a5308c803d25cd14dd42eee792a84295432dd781995fb270bd29ae90b431e8f74d56ea32bc80955ae81a52e5cacf6834da0ae4f9c805b436f3b562e415326da8b3a4df94e67b4e737b269d4277a03fe45a8f54cf8bc889f60848ea")] 12 | -------------------------------------------------------------------------------- /NeoLua/TypeExtensionHelpers.cs: -------------------------------------------------------------------------------- 1 | #region -- copyright -- 2 | // 3 | // Licensed to the Apache Software Foundation (ASF) under one 4 | // or more contributor license agreements. See the NOTICE file 5 | // distributed with this work for additional information 6 | // regarding copyright ownership. The ASF licenses this file 7 | // to you under the Apache License, Version 2.0 (the 8 | // "License"); you may not use this file except in compliance 9 | // with the License. You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, 14 | // software distributed under the License is distributed on an 15 | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | // KIND, either express or implied. See the License for the 17 | // specific language governing permissions and limitations 18 | // under the License. 19 | // 20 | #endregion 21 | using System; 22 | using System.Collections.Generic; 23 | using System.Diagnostics; 24 | using System.Linq; 25 | using System.Reflection; 26 | 27 | namespace Neo.IronLua 28 | { 29 | internal static class TypeExtensionHelpers 30 | { 31 | public static bool HasImplicitConversionToType(this Type declaringType, Type targetType) 32 | => declaringType.TryGetImplicitAssignmentOperatorToType(targetType, out _); 33 | 34 | public static bool HasImplicitConversionFromType(this Type declaringType, Type sourceType) 35 | => declaringType.TryGetImplicitAssignmentOperatorFromType(sourceType, out _); 36 | 37 | public static bool CanConvertTo(this Type sourceType, Type targetType) 38 | { 39 | Debug.Assert(targetType != sourceType); 40 | return GetAllImplicitOperators(sourceType).Any(CanImplicitlyCastToTarget); 41 | 42 | bool CanImplicitlyCastToTarget(MethodInfo mi) 43 | { 44 | var parameterInfos = mi.GetParameters(); 45 | Debug.Assert(parameterInfos[0].ParameterType == sourceType); 46 | var canConvertTo = CanAssign(mi.ReturnType, targetType); 47 | return canConvertTo; 48 | } 49 | } 50 | 51 | /// 52 | /// True if the source type can be converted to the target type. 53 | /// 54 | /// 55 | /// 56 | /// 57 | public static bool CanConvertFrom(this Type targetType, Type sourceType) 58 | { 59 | Debug.Assert(targetType != sourceType); 60 | return GetAllImplicitOperators(targetType).Any(CanImplicitlyConstructFromSource); 61 | 62 | bool CanImplicitlyConstructFromSource(MethodInfo mi) 63 | { 64 | var parameterInfos = mi.GetParameters(); 65 | var parameterType = parameterInfos[0].ParameterType; 66 | var canConvertTo = CanAssign(sourceType, parameterType); 67 | return canConvertTo; 68 | } 69 | } 70 | 71 | public static bool CanAssignFromPrimitiveType(this Type targetType, Type sourceType) 72 | { 73 | return CanAssignValueType(sourceType, targetType); 74 | } 75 | 76 | private static bool CanAssign(Type from, Type to) 77 | { 78 | if (from == to) return true; 79 | if (from.IsAssignableFrom(to)) return true; 80 | if (from.IsValueType && to.IsValueType && CanAssignValueType(from, to)) return true; 81 | 82 | return false; 83 | } 84 | 85 | private static bool TryGetImplicitAssignmentOperatorToType(this Type declaringType, Type toType, out MethodInfo implicitOperator) 86 | { 87 | Debug.Assert(declaringType != toType); 88 | implicitOperator = declaringType.GetMethods(BindingFlags.Public | BindingFlags.Static) 89 | .FirstOrDefault(mi => mi.Name == "op_Implicit" && mi.ReturnType == toType); 90 | if (implicitOperator is not null) 91 | { 92 | Debug.Assert(implicitOperator.GetParameters()[0].ParameterType == declaringType); 93 | return true; 94 | } 95 | 96 | return false; 97 | } 98 | 99 | private static bool TryGetImplicitAssignmentOperatorFromType(this Type declaringType, Type fromType, out MethodInfo implicitOperator) 100 | { 101 | Debug.Assert(declaringType != fromType); 102 | // There can only be a single implicit operator from a type 103 | var op = GetImplicitOperator(declaringType, fromType); 104 | if (op is not null) 105 | { 106 | Debug.Assert(op.ReturnType == declaringType); 107 | implicitOperator = op; 108 | return true; 109 | } 110 | 111 | implicitOperator = null; 112 | return false; 113 | } 114 | 115 | private static MethodInfo GetImplicitOperator(Type declaringType, Type fromType) 116 | => declaringType.GetMethod("op_Implicit", BindingFlags.Public | BindingFlags.Static, binder: null, new[] { fromType }, EmptyParameterModifier); 117 | 118 | private static IEnumerable GetAllImplicitOperators(Type declaringType) 119 | => declaringType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(mi => mi.Name == "op_ImplicitO"); 120 | 121 | private static ParameterModifier[] EmptyParameterModifier = new ParameterModifier[0]; 122 | 123 | private static bool CanAssignValueType(Type argType, Type parameterType) 124 | { 125 | if (argType == typeof(Int16)) 126 | return parameterType == typeof(Int16) || parameterType == typeof(Int32) || parameterType == typeof(Int64) 127 | || parameterType == typeof(Single) || parameterType == typeof(Double); 128 | if (argType == typeof(Int32)) 129 | return parameterType == typeof(Int32) || parameterType == typeof(Int64) || parameterType == typeof(Single) || parameterType == typeof(Double); 130 | if (argType == typeof(Int64)) 131 | return parameterType == typeof(Int64) || parameterType == typeof(Double); 132 | 133 | if (argType == typeof(Single)) 134 | return parameterType == typeof(Single) || parameterType == typeof(Double); 135 | if (argType == typeof(Double)) return parameterType == typeof(Double); 136 | return false; 137 | } 138 | 139 | public static bool IsParamArray(this ParameterInfo parameterInfo) 140 | => parameterInfo.GetCustomAttribute(typeof(ParamArrayAttribute), false) is not null; 141 | } 142 | } -------------------------------------------------------------------------------- /NeoSpeed/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /NeoSpeed/LuaInterface.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoSpeed/LuaInterface.dll -------------------------------------------------------------------------------- /NeoSpeed/NeoSpeed.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B57F94E3-E256-4CE2-B907-FF8B0E0E2683} 8 | Exe 9 | Properties 10 | NeoSpeed 11 | NeoSpeed 12 | v4.6 13 | 512 14 | SAK 15 | SAK 16 | SAK 17 | SAK 18 | 19 | 20 | 21 | 22 | x86 23 | true 24 | full 25 | true 26 | bin\Debug\ 27 | DEBUG 28 | prompt 29 | 4 30 | false 31 | 32 | 33 | x86 34 | pdbonly 35 | true 36 | bin\Release\ 37 | TRACE 38 | prompt 39 | 4 40 | false 41 | 42 | 43 | 44 | False 45 | .\LuaInterface.dll 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | PreserveNewest 81 | 82 | 83 | 84 | 85 | 86 | {09aebb35-719e-4e32-9836-f57d7d6f1607} 87 | NeoLua 88 | 89 | 90 | 91 | 98 | -------------------------------------------------------------------------------- /NeoSpeed/NeoSpeed.csproj.vspscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" 10 | } 11 | -------------------------------------------------------------------------------- /NeoSpeed/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace NeoSpeed 10 | { 11 | class Program 12 | { 13 | private static Neo.IronLua.ILuaDebug debugNeoLua = Neo.IronLua.Lua.StackTraceCompileOptions.DebugEngine; 14 | 15 | static void Main(string[] args) 16 | { 17 | string[] scripts = new string[] 18 | { 19 | Path.GetFullPath(@"..\..\Scripts\Empty.lua"), 20 | Path.GetFullPath(@"..\..\Scripts\Sum.lua"), 21 | Path.GetFullPath(@"..\..\Scripts\Sum_strict{0}.lua"), 22 | Path.GetFullPath(@"..\..\Scripts\Sum_echo.lua"), 23 | Path.GetFullPath(@"..\..\Scripts\String.lua"), 24 | Path.GetFullPath(@"..\..\Scripts\String_echo.lua"), 25 | Path.GetFullPath(@"..\..\Scripts\Delegate.lua"), 26 | Path.GetFullPath(@"..\..\Scripts\StringBuilder{0}.lua"), 27 | Path.GetFullPath(@"..\..\Scripts\CallStd.lua"), 28 | Path.GetFullPath(@"..\..\Scripts\TableIntSet.lua"), 29 | Path.GetFullPath(@"..\..\Scripts\TableIntGet.lua"), 30 | Path.GetFullPath(@"..\..\Scripts\TableVsList{0}.lua"), 31 | Path.GetFullPath(@"..\..\Scripts\TableString.lua"), 32 | }; 33 | 34 | Console.WriteLine(); 35 | Console.WriteLine("Rebuild cache:"); 36 | for (int i = 0; i < scripts.Length; i++) 37 | { 38 | string sScript1 = File.ReadAllText(String.Format(scripts[i], 1)); 39 | string sScript2 = File.ReadAllText(String.Format(scripts[i], 2)); 40 | double t1 = ExecuteScriptLoop(ExecuteLuaIntf, sScript1, 100); 41 | double t2 = ExecuteScriptLoop(ExecuteNeoLua, sScript2, 100); 42 | Console.WriteLine(" {0,-20}: LuaInterface {1,6:N1} ms NeoLua {2,6:N1} ms {3,6:N3}", 43 | Path.GetFileNameWithoutExtension(scripts[i].Replace("{0}", "")), 44 | t1, 45 | t2, 46 | t2 == 0.0 ? Double.NaN : t1 / t2 47 | ); 48 | } 49 | Console.WriteLine(); 50 | Console.WriteLine("Precompiled (no cache clear):"); 51 | debugNeoLua = null; 52 | for (int i = 0; i < scripts.Length; i++) 53 | { 54 | string sScript1 = File.ReadAllText(String.Format(scripts[i], 1)); 55 | string sScript2 = File.ReadAllText(String.Format(scripts[i], 2)); 56 | double t1 = ExecuteLuaIntfCompiled(sScript1, 100); 57 | double t2 = ExecuteNeoLuaCompiled(sScript2, 100); 58 | Console.WriteLine(" {0,-20}: LuaInterface {1,6:N1} ms NeoLua {2,6:N1} ms {3,6:N3}", 59 | Path.GetFileNameWithoutExtension(scripts[i].Replace("{0}", "")), 60 | t1, 61 | t2, 62 | t2 == 0.0 ? Double.NaN : t1 / t2 63 | ); 64 | } 65 | Console.WriteLine(); 66 | Console.WriteLine("Precompiled (no cache clear, debug):"); 67 | debugNeoLua = Neo.IronLua.Lua.StackTraceCompileOptions.DebugEngine; 68 | for (int i = 0; i < scripts.Length; i++) 69 | { 70 | string sScript1 = File.ReadAllText(String.Format(scripts[i], 1)); 71 | string sScript2 = File.ReadAllText(String.Format(scripts[i], 2)); 72 | double t1 = ExecuteLuaIntfCompiled(sScript1, 100); 73 | double t2 = ExecuteNeoLuaCompiled(sScript2, 100); 74 | Console.WriteLine(" {0,-20}: LuaInterface {1,6:N1} ms NeoLua {2,6:N1} ms {3,6:N3}", 75 | Path.GetFileNameWithoutExtension(scripts[i].Replace("{0}", "")), 76 | t1, 77 | t2, 78 | t2 == 0.0 ? Double.NaN : t1 / t2 79 | ); 80 | } 81 | Console.WriteLine(); 82 | Console.WriteLine(v == 1801800 ? "All called." : String.Format("{0} != {1}", v, 1201200)); 83 | 84 | Console.ReadLine(); 85 | } 86 | 87 | private static double ExecuteLuaIntfCompiled(string sScript, int iLoops) 88 | { 89 | using (LuaInterface.Lua lua = new LuaInterface.Lua()) 90 | { 91 | lua.RegisterFunction("test", null, typeof(Program).GetMethod("LuaTest")); 92 | lua.RegisterFunction("echo", null, typeof(Program).GetMethod("LuaEcho")); 93 | LuaInterface.LuaFunction f = lua.LoadString(sScript, "test"); 94 | 95 | Stopwatch sw = new Stopwatch(); 96 | sw.Start(); 97 | 98 | for (int i = 0; i < iLoops; i++) 99 | DebugOut("LuaIntf-C", i, f.Call()); 100 | 101 | return sw.ElapsedMilliseconds / (double)iLoops; 102 | } 103 | } 104 | 105 | private static double ExecuteNeoLuaCompiled(string sScript, int iLoops) 106 | { 107 | using (Neo.IronLua.Lua lua = new Neo.IronLua.Lua()) 108 | { 109 | Neo.IronLua.LuaChunk chunk = lua.CompileChunk(sScript, "test", new Neo.IronLua.LuaCompileOptions() { DebugEngine = debugNeoLua }); 110 | Neo.IronLua.LuaGlobal g = lua.CreateEnvironment(); 111 | g["test"] = new Action(LuaTest); 112 | g["echo"] = new Func(LuaEcho); 113 | 114 | Stopwatch sw = new Stopwatch(); 115 | sw.Start(); 116 | for (int i = 0; i < iLoops; i++) 117 | DebugOut("NeoLua-C", i, g.DoChunk(chunk)); 118 | return sw.ElapsedMilliseconds / (double)iLoops; 119 | } 120 | } 121 | 122 | private static double ExecuteScriptLoop(Func f, string sScript, int iLoops) 123 | { 124 | long sum = 0; 125 | for (int i = 0; i < iLoops; i++) 126 | sum += f(i, sScript); 127 | return sum / (double)iLoops; 128 | } // func ExecuteScriptLoop 129 | 130 | private static long ExecuteLuaIntf(int i, string sScript) 131 | { 132 | Stopwatch sw = new Stopwatch(); 133 | sw.Start(); 134 | using (LuaInterface.Lua lua = new LuaInterface.Lua()) 135 | { 136 | lua.RegisterFunction("test", null, typeof(Program).GetMethod("LuaTest")); 137 | lua.RegisterFunction("echo", null, typeof(Program).GetMethod("LuaEcho")); 138 | DebugOut("LuaIntf", i, lua.DoString(sScript, "test")); 139 | } 140 | return sw.ElapsedMilliseconds; 141 | } // proc ExecuteLuaIntf 142 | 143 | //private static Neo.IronLua.Lua lua = new Neo.IronLua.Lua(); 144 | private static long ExecuteNeoLua(int i, string sScript) 145 | { 146 | Stopwatch sw = new Stopwatch(); 147 | sw.Start(); 148 | using (Neo.IronLua.Lua lua = new Neo.IronLua.Lua()) 149 | { 150 | Neo.IronLua.LuaGlobal g = lua.CreateEnvironment(); 151 | g["test"] = new Action(LuaTest); 152 | g["echo"] = new Func(LuaEcho); 153 | DebugOut("NeoLua", i, g.DoChunk(sScript, "test")); 154 | } 155 | return sw.ElapsedMilliseconds; 156 | } 157 | 158 | private static int v = 0; 159 | 160 | public static void LuaTest(int i) 161 | { 162 | v++; 163 | } 164 | 165 | public static object LuaEcho(object e) 166 | { 167 | v++; 168 | return e; 169 | } 170 | 171 | private static void DebugOut(string sLua, int i, object[] r) 172 | { 173 | //Debug.Print("Call {0}:{1}: {2}", sLua, i, r != null && r.Length == 1 ? r[0] : ""); 174 | } // proc DebugOut 175 | 176 | private static int ConvDummy(object value) 177 | { 178 | return (int)value; 179 | } 180 | 181 | private static long SumLuaCS() 182 | { 183 | Stopwatch sw = new Stopwatch(); 184 | sw.Start(); 185 | 186 | object sum = 0; 187 | for (object i = 0; ConvDummy(i) < 1000; i = ConvDummy(i) + 1) 188 | sum = ConvDummy(sum) + ConvDummy(LuaEcho(i)); 189 | 190 | return sw.ElapsedMilliseconds; 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /NeoSpeed/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // Allgemeine Informationen über eine Assembly werden über die folgenden 6 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 7 | // die mit einer Assembly verknüpft sind. 8 | [assembly: AssemblyTitle("NeoSpeed")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("NeoSpeed")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 18 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 19 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. 20 | [assembly: ComVisible(false)] 21 | 22 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 23 | [assembly: Guid("d9deee1b-8bee-4c5c-8c41-7a9ed1cc8901")] 24 | 25 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 26 | // 27 | // Hauptversion 28 | // Nebenversion 29 | // Buildnummer 30 | // Revision 31 | // 32 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 33 | // übernehmen, indem Sie "*" eingeben: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /NeoSpeed/Scripts/CallStd.lua: -------------------------------------------------------------------------------- 1 | local a; 2 | for i = 1,10000,1 do 3 | a = type(""); 4 | end; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/Delegate.lua: -------------------------------------------------------------------------------- 1 | for i = 0, 1000, 1 do 2 | test(i); 3 | end; 4 | -------------------------------------------------------------------------------- /NeoSpeed/Scripts/Empty.lua: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /NeoSpeed/Scripts/String.lua: -------------------------------------------------------------------------------- 1 |  2 | local sum = 0; 3 | 4 | for i = 0, 1000, 1 do 5 | sum = sum .. "."; 6 | end; 7 | 8 | return sum; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/StringBuilder1.lua: -------------------------------------------------------------------------------- 1 | StringBuilder = luanet.import_type("System.Text.StringBuilder"); 2 | 3 | local sb = StringBuilder(); 4 | 5 | for i = 0,1000,1 do 6 | sb:Append("."); 7 | end; 8 | 9 | return sb:ToString(); -------------------------------------------------------------------------------- /NeoSpeed/Scripts/StringBuilder2.lua: -------------------------------------------------------------------------------- 1 | const StringBuilder typeof System.Text.StringBuilder; 2 | local sb : StringBuilder = StringBuilder(); 3 | 4 | for i = 0,1000,1 do 5 | sb:Append("."); 6 | end; 7 | 8 | return sb:ToString(); -------------------------------------------------------------------------------- /NeoSpeed/Scripts/String_echo.lua: -------------------------------------------------------------------------------- 1 |  2 | local sum = 0; 3 | 4 | for i = 0, 1000, 1 do 5 | sum = sum .. echo("."); 6 | end; 7 | 8 | return sum; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/Sum.lua: -------------------------------------------------------------------------------- 1 |  2 | local sum = 0; 3 | 4 | for i = 0, 1000, 1 do 5 | sum = sum + i; 6 | end; 7 | 8 | return sum; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/Sum_echo.lua: -------------------------------------------------------------------------------- 1 |  2 | local sum = 0; 3 | 4 | for i = 0, 1000, 1 do 5 | sum = sum + echo(i); 6 | end; 7 | 8 | return sum; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/Sum_strict1.lua: -------------------------------------------------------------------------------- 1 |  2 | local sum = 0; 3 | 4 | for i = 0, 1000, 1 do 5 | sum = sum + i; 6 | end; 7 | 8 | return sum; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/Sum_strict2.lua: -------------------------------------------------------------------------------- 1 |  2 | local sum : int = 0; 3 | 4 | for i = 0, 1000, 1 do 5 | sum = sum + i; 6 | end; 7 | 8 | return sum; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/TableIntGet.lua: -------------------------------------------------------------------------------- 1 |  2 | local t = {}; 3 | -- C-Lua schneller 4 | for i = 1,10000,1 do 5 | t[i] = i; 6 | end; 7 | 8 | -- interessant! C-Lua ziemlich lahm 9 | for i = 1,100,1 do 10 | table.remove(t, i + 1000); 11 | end; 12 | for i = 1,100,1 do 13 | table.insert(t, i + 1000, 1); 14 | end; 15 | 16 | -- C-Lua schneller 17 | local sum = 0; 18 | for i = 1,10000,1 do 19 | sum = sum + t[i]; 20 | end; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/TableIntSet.lua: -------------------------------------------------------------------------------- 1 |  2 | local t = {}; 3 | for i = 1,10000,1 do 4 | t[i] = i; 5 | end; 6 | -------------------------------------------------------------------------------- /NeoSpeed/Scripts/TableString.lua: -------------------------------------------------------------------------------- 1 |  2 | local t = {}; 3 | for i = 1,10000,1 do 4 | t[tostring(i)] = i; 5 | end; 6 | 7 | local sum = 0; 8 | for i = 1,10000,1 do 9 | sum = sum + t[tostring(i)]; 10 | end; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/TableVsList1.lua: -------------------------------------------------------------------------------- 1 |  2 | local t = {}; 3 | for i = 1,10000,1 do 4 | t[i] = i; 5 | end; 6 | 7 | local sum = 0; 8 | for i = 1,10000,1 do 9 | sum = sum + t[i]; 10 | end; -------------------------------------------------------------------------------- /NeoSpeed/Scripts/TableVsList2.lua: -------------------------------------------------------------------------------- 1 |  2 | local t = clr.System.Collections.Generic.List[clr.System.Int32](); 3 | for i = 1,10000,1 do 4 | t:Add(i); 5 | end; 6 | 7 | local sum = 0; 8 | for i = 0,10000-1,1 do 9 | sum = sum + t[i]; 10 | end; -------------------------------------------------------------------------------- /NeoSpeed/lua.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/NeoSpeed/lua.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NeoLua 2 | ====== 3 | 4 | A Lua implementation for the Dynamic Language Runtime (DLR). 5 | 6 | ## Introduction 7 | 8 | NeoLua is an implementation of the Lua language. Currently, the implementation is on 9 | the level of [Lua_5.3](http://www.lua.org/) (http://www.lua.org/manual/5.3/manual.html). 10 | The goal is to follow the reference of the C-Lua implementation and combine this with full 11 | .NET Framework support. That means, it should be easy to call .NET functions from Lua and it should 12 | be easy access variables and functions from a .net language (e.g. C#, VB.NET, ...). 13 | 14 | NeoLua is implemented in C# and uses the [Dynamic Language Runtime](https://dlr.codeplex.com/). It therefore 15 | integrates very well with the .NET Framework. 16 | 17 | ### Quickstart 18 | 19 | You can play and test the language with the tool NeoCmd. 20 | 21 | ![NeoCmd](doc/imgs/Image.png) 22 | 23 | Or there are two easy ways to use NeoLua in your project. 24 | 25 | * Download the Neo.Lua.dll and add the reference. For full desktop support also a reference to Neo.Lua.Desktop.dll is useful. 26 | * Install the [NuGet package](http://www.nuget.org/packages/NeoLua/) of NeoLua. 27 | 28 | 29 | Simple example: 30 | ```C# 31 | using (Lua lua = new Lua()) // Create the Lua script engine 32 | { 33 | dynamic env = lua.CreateEnvironment(); // Create a environment 34 | env.dochunk("a = 'Hallo World!';", "test.lua"); // Create a variable in Lua 35 | Console.WriteLine(env.a); // Access a variable in C# 36 | env.dochunk("function add(b) return b + 3; end;", "test.lua"); // Create a function in Lua 37 | Console.WriteLine("Add(3) = {0}", env.add(3)); // Call the function in C# 38 | } 39 | ``` 40 | 41 | ```VB 42 | Using lua As Lua = New Lua ' Create the Lua script engine 43 | Dim env As Object = lua.CreateEnvironment(Of LuaGlobal)() ' Create a environment 44 | env.dochunk("a = 'Hallo World!';", "test.lua") ' Create a variable in Lua 45 | Console.WriteLine(env.a) ' Access a variable in VB 46 | env.dochunk("function add(b) return b + 3; end;", "test.lua") ' Create a function in Lua 47 | Console.WriteLine("Add(3) = {0}", (New LuaResult(env.add(3)))(0)) ' Call the function in VB 48 | End Using 49 | ``` 50 | 51 | A more "complex" script, that shows the interaction between lua and .net: 52 | ```Lua 53 | local t = clr.System.Int32[](6, 8, 9, 19);", 54 | return t:Sum(), t:Where(function(c : int) : bool return c < 10 end):Sum() 55 | ``` 56 | 57 | NeoLua is a .NET portable assembly (IL) for 58 | * .NET Framework 4.5.1 59 | * Windows Phone 8.1 60 | * Windows Store Apps 8.1 61 | * Xamarin.Android 62 | 63 | There will be no support for .NET Frameworks lower than 4.5. 64 | 65 | It does not work with 66 | * Xamarin.iOS. 67 | or any .NET runtime that does not support code generation. 68 | 69 | 70 | ### What NeoLua is useful for 71 | 72 | * Outsource the logic of your application into scripts 73 | * Structuring of logic 74 | * Build a dynamic configuration system, with functions and variables 75 | * As a formula parser 76 | * ... 77 | 78 | So, this could be reliable partner for your compiled .NET application or engine (e.g. game engines). 79 | 80 | ### What I did not have in mind 81 | 82 | * Compiling libraries 83 | * Standalone applications 84 | 85 | ### Advantages of NeoLua 86 | 87 | * Dynamic access between Lua script and and the host application/.NET Framework and vice-versa. 88 | * NeoLua is based on the DLR. So you get compiled code that is collectable and well-optimized. 89 | * It is compatible with the .NET world (e.g. C#, VB.NET, IronPython, ...). 90 | * Full and easy access to the .NET Framework or your own libraries (with no stub code). 91 | * A rich implementation of the Lua table, for a got integration in the .NET world e.g. binding, enumeration, ... 92 | * A .NET Framework garbage collector that is well-tested and very fast. 93 | * Pure IL (x86, x64 support) 94 | 95 | ### Drawbacks of NeoLua 96 | 97 | * It is not [100% compatible](doc/06_std.md) to Lua. But I will try very hard. 98 | * No deployment of precompiled scripts. 99 | 100 | ### Drawbacks of bridges to c-lua, that are solved with NeoLua 101 | 102 | * You have two memory managers and so you have to marshal every data between these two worlds. That takes time and there are a lot pitfalls to get memory leaks. 103 | * C-Lua interprets its own bytecode. The code is not compiled to machine code. 104 | 105 | ## Documentation 106 | 107 | *This documention has the same structure like the official reference ([Lua 5.3](http://www.lua.org/manual/5.3/manual.html)), so it should be easy to compare the two worlds.* 108 | 109 | 1. Introduction 110 | 2. [Basic concepts](doc/02_basics.md) 111 | 3. [Language](doc/03_language.md) 112 | 4. Application Program Interface 113 | 1. [Getting started](doc/04_01_start.md) 114 | 2. [Script engine](doc/04_02_engine.md) 115 | 3. [Chunks](doc/04_03_chunk.md) 116 | 4. [Table's](doc/04_04_table.md) 117 | 5. The Auxiliary Library 118 | 1. [clr library](doc/05_01_clr.md) 119 | 2. [Extent lua table](doc/05_02_extent.md) 120 | 3. [Debugging](doc/05_03_debug.md) 121 | 6. [Standard libraries](doc/06_std.md) 122 | 7. [NeoCmd](doc/07_neocmd.md) 123 | 124 | If there is something unclear, wrong or misunderstanding please use the discussions. 125 | 126 | ## Projects that use this library 127 | 128 | * Data Exchange Server: https://github.com/twdes/des 129 | 130 | ## Links 131 | 132 | * Article on CodeProject: http://www.codeproject.com/Articles/674128/NeoLua-Lua-for-the-net-dynamic-lanuguage-runtime 133 | * NuGet package: https://www.nuget.org/packages/NeoLua/ 134 | 135 | You want pay for your request, contact us under https://tecware-gmbh.de/kontakt.html (only for members of the european union). 136 | 137 | Or you want todo something good for other people. Donate to https://angelman.de/unser-verein/spenden/ (only in german) 138 | -------------------------------------------------------------------------------- /VBtest/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /VBtest/Module1.vb: -------------------------------------------------------------------------------- 1 | Option Strict On 2 | Imports Neo.IronLua 3 | 4 | Module Module1 5 | 6 | Private Sub TestStrict() 7 | Using l As Lua = New Lua ' create the lua script engine 8 | Dim g As LuaGlobal = l.CreateEnvironment(Of LuaGlobal)() ' create a environment 9 | g.DoChunk("a = 'Hallo World!';", "test.lua") ' create a variable in lua 10 | Console.WriteLine(g("a").ToString()) ' access a variable in VB 11 | g.DoChunk("function add(b) return b + 3; end;", "test.lua") ' create a function in lua 12 | Console.WriteLine("Add(3) = {0}", g.CallMember("add", 3)) ' call the function in VB 13 | End Using 14 | End Sub 15 | 16 | Sub Main() 17 | Console.WriteLine("Strict on") 18 | TestStrict() 19 | 'Console.WriteLine("Strict off VB only") 20 | 'TestDynamicVBOnly() 21 | Console.WriteLine("Strict off") 22 | Module2.TestDynamic() 23 | Console.ReadLine() 24 | End Sub 25 | 26 | End Module 27 | -------------------------------------------------------------------------------- /VBtest/Module2.vb: -------------------------------------------------------------------------------- 1 | Option Strict Off 2 | 3 | Imports Neo.IronLua 4 | 5 | Module Module2 6 | Public Sub TestDynamicVBOnly() 7 | Dim f = Function(ByVal o) As LuaResult 8 | Return New LuaResult(o + 3) 9 | End Function 10 | 11 | Dim f2 = DirectCast(f, Object) 12 | Dim tname = f.GetType() 13 | Dim tname2 = f2.GetType() 14 | Console.WriteLine("t: {0}", tname) 15 | Console.WriteLine("t: {0}", tname2) 16 | Console.WriteLine("Add(3) = {0}", f(3)) 17 | Console.WriteLine("Add(3) = {0}", f2(3)) ' why is this crashing 18 | End Sub 19 | 20 | Public Sub TestDynamic() 21 | Using l As Lua = New Lua ' create the lua script engine 22 | Dim g As Object = l.CreateEnvironment(Of LuaGlobal)() ' create a environment 23 | g.dochunk("a = 'Hallo World!';", "test.lua") ' create a variable in lua 24 | Console.WriteLine(g.a) ' access a variable in VB 25 | g.dochunk("function add(b) return b + 3; end;", "test.lua") ' create a function in lua 26 | Console.WriteLine("Add(3) = {0}", (New LuaResult(g.add(3)))(0)) ' call the function in VB 27 | End Using 28 | End Sub 29 | End Module 30 | -------------------------------------------------------------------------------- /VBtest/My Project/Application.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.42000 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | -------------------------------------------------------------------------------- /VBtest/My Project/Application.myapp: -------------------------------------------------------------------------------- 1 |  2 | 3 | false 4 | false 5 | 0 6 | true 7 | 0 8 | 2 9 | true 10 | 11 | -------------------------------------------------------------------------------- /VBtest/My Project/AssemblyInfo.vb: -------------------------------------------------------------------------------- 1 | Imports System 2 | Imports System.Reflection 3 | Imports System.Runtime.InteropServices 4 | 5 | ' General Information about an assembly is controlled through the following 6 | ' set of attributes. Change these attribute values to modify the information 7 | ' associated with an assembly. 8 | 9 | ' Review the values of the assembly attributes 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 'The following GUID is for the ID of the typelib if this project is exposed to COM 21 | 22 | 23 | ' Version information for an assembly consists of the following four values: 24 | ' 25 | ' Major Version 26 | ' Minor Version 27 | ' Build Number 28 | ' Revision 29 | ' 30 | ' You can specify all the values or you can default the Build and Revision Numbers 31 | ' by using the '*' as shown below: 32 | ' 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /VBtest/My Project/Resources.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.42000 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | Namespace My.Resources 16 | 17 | 'This class was auto-generated by the StronglyTypedResourceBuilder 18 | 'class via a tool like ResGen or Visual Studio. 19 | 'To add or remove a member, edit your .ResX file then rerun ResGen 20 | 'with the /str option, or rebuild your VS project. 21 | ''' 22 | ''' A strongly-typed resource class, for looking up localized strings, etc. 23 | ''' 24 | _ 28 | Friend Module Resources 29 | 30 | Private resourceMan As Global.System.Resources.ResourceManager 31 | 32 | Private resourceCulture As Global.System.Globalization.CultureInfo 33 | 34 | ''' 35 | ''' Returns the cached ResourceManager instance used by this class. 36 | ''' 37 | _ 38 | Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager 39 | Get 40 | If Object.ReferenceEquals(resourceMan, Nothing) Then 41 | Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("VBtest.Resources", GetType(Resources).Assembly) 42 | resourceMan = temp 43 | End If 44 | Return resourceMan 45 | End Get 46 | End Property 47 | 48 | ''' 49 | ''' Overrides the current thread's CurrentUICulture property for all 50 | ''' resource lookups using this strongly typed resource class. 51 | ''' 52 | _ 53 | Friend Property Culture() As Global.System.Globalization.CultureInfo 54 | Get 55 | Return resourceCulture 56 | End Get 57 | Set(ByVal value As Global.System.Globalization.CultureInfo) 58 | resourceCulture = value 59 | End Set 60 | End Property 61 | End Module 62 | End Namespace 63 | -------------------------------------------------------------------------------- /VBtest/My Project/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /VBtest/My Project/Settings.Designer.vb: -------------------------------------------------------------------------------- 1 | '------------------------------------------------------------------------------ 2 | ' 3 | ' This code was generated by a tool. 4 | ' Runtime Version:4.0.30319.42000 5 | ' 6 | ' Changes to this file may cause incorrect behavior and will be lost if 7 | ' the code is regenerated. 8 | ' 9 | '------------------------------------------------------------------------------ 10 | 11 | Option Strict On 12 | Option Explicit On 13 | 14 | 15 | Namespace My 16 | 17 | _ 20 | Partial Friend NotInheritable Class MySettings 21 | Inherits Global.System.Configuration.ApplicationSettingsBase 22 | 23 | Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) 24 | 25 | #Region "My.Settings Auto-Save Functionality" 26 | #If _MyType = "WindowsForms" Then 27 | Private Shared addedHandler As Boolean 28 | 29 | Private Shared addedHandlerLockObject As New Object 30 | 31 | _ 32 | Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) 33 | If My.Application.SaveMySettingsOnExit Then 34 | My.Settings.Save() 35 | End If 36 | End Sub 37 | #End If 38 | #End Region 39 | 40 | Public Shared ReadOnly Property [Default]() As MySettings 41 | Get 42 | 43 | #If _MyType = "WindowsForms" Then 44 | If Not addedHandler Then 45 | SyncLock addedHandlerLockObject 46 | If Not addedHandler Then 47 | AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings 48 | addedHandler = True 49 | End If 50 | End SyncLock 51 | End If 52 | #End If 53 | Return defaultInstance 54 | End Get 55 | End Property 56 | End Class 57 | End Namespace 58 | 59 | Namespace My 60 | 61 | _ 64 | Friend Module MySettingsProperty 65 | 66 | _ 67 | Friend ReadOnly Property Settings() As Global.VBtest.My.MySettings 68 | Get 69 | Return Global.VBtest.My.MySettings.Default 70 | End Get 71 | End Property 72 | End Module 73 | End Namespace 74 | -------------------------------------------------------------------------------- /VBtest/My Project/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VBtest/VBtest.vbproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {875DB2E3-F857-4845-9DE8-A63EBA59FC41} 8 | Exe 9 | VBtest.Module1 10 | VBtest 11 | VBtest 12 | 512 13 | Console 14 | v4.6 15 | true 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | true 22 | true 23 | bin\Debug\ 24 | VBtest.xml 25 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | false 31 | true 32 | true 33 | bin\Release\ 34 | VBtest.xml 35 | 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 36 | 37 | 38 | On 39 | 40 | 41 | Binary 42 | 43 | 44 | Off 45 | 46 | 47 | On 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | True 76 | Application.myapp 77 | 78 | 79 | True 80 | True 81 | Resources.resx 82 | 83 | 84 | True 85 | Settings.settings 86 | True 87 | 88 | 89 | 90 | 91 | VbMyResourcesResXFileCodeGenerator 92 | Resources.Designer.vb 93 | My.Resources 94 | Designer 95 | 96 | 97 | 98 | 99 | MyApplicationCodeGenerator 100 | Application.Designer.vb 101 | 102 | 103 | SettingsSingleFileGenerator 104 | My 105 | Settings.Designer.vb 106 | 107 | 108 | 109 | 110 | 111 | {09aebb35-719e-4e32-9836-f57d7d6f1607} 112 | NeoLua 113 | 114 | 115 | 116 | 123 | -------------------------------------------------------------------------------- /doc/02_basics.md: -------------------------------------------------------------------------------- 1 | # Basic Concepts 2 | ## Values and Types 3 | 4 | NeoLua is not a dynamically typed language, it just looks like. Variables have always a type (at least `System.Object`). That behavior differs to c-lua. 5 | 6 | NeoLua supports all CLR types. If there is type conversion necessary, it is done automatically. Also dynamic types are supported. 7 | 8 | ```Lua 9 | local a = "5"; -- a string is assigned to a local variable of the type object 10 | local b = {}; -- object assigned with a empty table 11 | b.c = a + 8; -- the variable "a" is converted to an integer and assigned to the dynamic member of an table 12 | ``` 13 | 14 | The following table shows the types of the lua constants: 15 | 16 | | Lua | Example | CLR | Difference | 17 | | :-----------|:---------:|:------|:------------ | 18 | | nil | | `System.Object` | | 19 | | false | | `System.Boolean` | | 20 | | true | | `System.Boolean` | | 21 | | number | `1.45` | `System.Double` | | 22 | | number | `23` | `System.IntXX` | Lua will choose the correct size of the interger. | 23 | | string | `"Test"` | `System.String` | Difference to 8bit string of lua. | 24 | | function | `function() end;` | `System.Delegate` | All lua functions are compiled to delegates. | 25 | | userdata | | Does not exists. | All values have there initial CLR-type. | 26 | | thread | | Not implemented. | | 27 | | table | `{1}` | `Neo.IronLua.LuaTable` | | 28 | 29 | For the conversion between types NeoLua uses the: 30 | * rules of Lua or C# 31 | * dynamic type rules 32 | * `implicit`/`explicit` operators (add static parse methods) 33 | 34 | ```Lua 35 | local a = 23 + "42"; -- "42" will be converted to integer 36 | local b = 23 .. "42"; -- 23 will be converted to string 37 | local c : byte = "23"; -- 23 will converted to a unsigned 8 bit integer 38 | local d : int = nil; -- will be converted to 0 39 | ``` 40 | 41 | The type casting/converting is one of the most complex part of this implemention. It will help to hold a script clean, please help to improve it. 42 | 43 | ## Environment 44 | 45 | There are two classes they important to create/run a lua script. 46 | 47 | First there is the script engine (`Lua`) that is responsible for compiling the scripts into chunks and caching the dynamic calls/requires. 48 | 49 | The second is global environment (`LuaGlobal`) on which chunks are executed. This table holds all global variables and defines the basic functions and packages. 50 | 51 | ###### Create the script engine and a environment: 52 | ```C# 53 | using (Lua l = new Lua()) 54 | { 55 | var g = l.CreateEnvironment(); 56 | ... 57 | ``` 58 | 59 | Normally, you need only one script engine per application. In rare cases it is useful to have more than one. 60 | 61 | For accessing and manipulation the environment see under [Global/Table's](doc/04_04_table.md), create your own environment see under extent tables. 62 | 63 | It is also possible to create plain delegates without any environment (see [Script engine](doc/04_02_engine.md)). 64 | 65 | ## Error Handling 66 | 67 | NeoLua uses the CLR exception handling and introduces two new exception classes. LuaParseException and LuaRuntimeException. 68 | 69 | The parse exception is thrown during the parsing, to inform about syntactical errors. The 70 | runtime exception is for all runtime errors. Overflow- or DivByZero exception will not 71 | be catch or converted. The lua error-function creates a LuaRuntimeException. 72 | 73 | If you need a stack trace to the exception, you need to compile the script with 74 | debug information. With the method `LuaExceptionData.GetData` you can retrieve for all exceptions a lua stacktrace. 75 | 76 | It is also possible to implement your own concept, for backtraces and debugging. 77 | 78 | ## Metatables and Metamethods 79 | 80 | Every lua table has a member, that holds the metatable (`__metatable`). 81 | 82 | ```C# 83 | ta = { __add = function(a, b) 84 | return a.v + b.v; 85 | end 86 | }; 87 | 88 | t1 = { __metatable = ta, v = 40 }; 89 | t2 = { __metatable = ta, v = 2 }; 90 | 91 | return t1 + t2; 92 | 93 | ``` 94 | 95 | | Member | Signature | 96 | |--------------|-------------------------------------| 97 | | `__add` | `(table, object) : object` | 98 | | | `:(object) : object` | 99 | | `__sub` | `(table, object) : object` | 100 | | | `:(object) : object` | 101 | | `__mul` | `(table, object) : object` | 102 | | | `:(object) : object` | 103 | | `__div` | `(table, object) : object` | 104 | | | `:(object) : object` | 105 | | `__mod` | `(table, object) : object` | 106 | | | `:(object) : object` | 107 | | `__pow` | `(table, object) : object` | 108 | | | `:(object) : object` | 109 | | `__idiv` | `(table, object) : object` | 110 | | | `:(object) : object` | 111 | | `__unm` | `(table) : object` | 112 | | | `:()object` | 113 | | `__band` | `(table, object) : object` | 114 | | | `:(object) : object` | 115 | | `__bor` | `(table, object) : object` | 116 | | | `:(object) : object` | 117 | | `__bxor` | `(table, object) : object` | 118 | | | `:(object) : object` | 119 | | `__bnot` | `(table) : object` | 120 | | | `:() : object` | 121 | | `__shl` | `(table, object) : object` | 122 | | | `:(object) : object` | 123 | | `__shr` | `(table, object) : object` | 124 | | | `:(object) : object` | 125 | | `__concat` | `(table, object) : object` | 126 | | | `:(object) : object` | 127 | | `__len` | `(table) : object` | 128 | | | `:() : object` | 129 | | `__lt` | `(table, object) : bool` | 130 | | | `:(object) : object` | 131 | | `__le` | `(table, object) : bool` | 132 | | | `:(object) : object` | 133 | | `__index` | `(table, key) : object` | 134 | | | `:(key) : object` | 135 | | `__newindex` | `(table, key, value) : object` | 136 | | | `:(key, value) : object` | 137 | | `__call` | `(table, object, ...) : result` | 138 | | | `:(object, ...) : result` | 139 | | `__changed` | `:(object):void` | 140 | 141 | ## Garbage Collection 142 | 143 | ** - is done by the clr -** 144 | 145 | ## Coroutines 146 | 147 | Coroutines are implemented in the LuaThread class. This class creates a managed thread for every coroutine. 148 | The resume-steps can run asynchronous (`:BeginResume`, `:EndResume`). 149 | 150 | The NeoLua-Runtime is threadsafe, so it is possible to use the multithreading features from the .net framework. -------------------------------------------------------------------------------- /doc/03_language.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/doc/03_language.md -------------------------------------------------------------------------------- /doc/04_01_start.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | In this section I will show a more complex example, how NeoLua is used. 4 | 5 | This example only works with the desktop NeoLua. 6 | 7 | ###### Host program (C#): 8 | ```C# 9 | public static class Program 10 | { 11 | public const string ProgramSource = "local a, b = tonumber(read(\"a\")), tonumber(read(\"b\"));\n\n" + 12 | "local PrintResult = function(o, op)\n" + 13 | " print(o.. ' = ' .. a..op..b);\n" + 14 | "end;\n\n" + 15 | "PrintResult(a + b, \" + \");\n" + 16 | "PrintResult(a - b, \" - \");\n" + 17 | "PrintResult(a * b, \" * \");\n" + 18 | "PrintResult(a / b, \" / \");\n" + 19 | "PrintResult(a // b, \" // \");\n"; 20 | 21 | public static void Main1(string[] args) 22 | { 23 | // create lua script engine 24 | using (var l = new Lua()) 25 | { 26 | // create an environment, that is associated to the lua scripts 27 | dynamic g = l.CreateEnvironment(); 28 | 29 | // register new functions 30 | g.print = new Action(Print); 31 | g.read = new Func(Read); 32 | 33 | 34 | var chunk = l.CompileChunk(ProgramSource, "test.lua", new LuaCompileOptions() { DebugEngine = LuaStackTraceDebugger.Default }); // compile the script with debug informations, that is needed for a complete stack trace 35 | 36 | try 37 | { 38 | g.dochunk(chunk); // execute the chunk 39 | } 40 | catch (Exception e) 41 | { 42 | Console.WriteLine("Expception: {0}", e.Message); 43 | var d = LuaExceptionData.GetData(e); // get stack trace 44 | Console.WriteLine("StackTrace: {0}", d.FormatStackTrace(0, false)); 45 | } 46 | } 47 | } // Main 48 | 49 | private static void Print(object[] texts) 50 | { 51 | foreach (object o in texts) 52 | Console.Write(o); 53 | Console.WriteLine(); 54 | } // proc Print 55 | 56 | private static string Read(string sLabel) 57 | { 58 | Console.Write(sLabel); 59 | Console.Write(": "); 60 | return Console.ReadLine(); 61 | } // func Read 62 | } // class Program 63 | ``` 64 | 65 | ###### Lua-Script (without escapes) 66 | ```Lua 67 | local a, b = tonumber(read("a")), tonumber(read("b")); 68 | 69 | function PrintResult(o, op) 70 | print(o .. ' = ' .. a .. op .. b); 71 | end; 72 | 73 | PrintResult(a + b, " + "); 74 | PrintResult(a - b, " - "); 75 | PrintResult(a * b, " * "); 76 | PrintResult(a / b, " / "); 77 | ``` -------------------------------------------------------------------------------- /doc/04_02_engine.md: -------------------------------------------------------------------------------- 1 | # Script engine 2 | 3 | The `Lua` class holds all together, that is needed for the compile and the runtime process. Normally you need only one instance per 4 | application. But sometimes it is useful to have more than one e.g. multithread scenarios. 5 | 6 | Main task for `Lua` are: 7 | * Compiling scripts to chunks 8 | * Cache dynamic binding rules, they resolved during runtime 9 | * Language runtime methods 10 | * Reflection cache during parsing 11 | 12 | ## `CompileChunk(...)` 13 | 14 | Compiles a script to a chunk. 15 | 16 | This method is very useful, if you want to execute a chunk more than one times. 17 | 18 | | Argument | Description | 19 | |:---------|:------------| 20 | | `sFileName`, `sCode`, `sName`, `tr` | Defines the script code and the name. | 21 | | `debug` | It is possible to manipulate the chunk creation to inject debug functionality. `null` creates plan chunks without any debugging functionality. | 22 | | `args` | Defines arguments for the chunk. So it is possible define arguments for the chunk. A chunk that is compiled with `CompileChunk` has at least one argument `G`, the global environment. | 23 | 24 | see [Chunks](04_03_chunk.md) 25 | 26 | ## `LuaGlobal CreateEnvironment` 27 | 28 | Creates a new LuaTable, that is associated to the lua script engine and acts as a standard lua environment. 29 | 30 | It is also possible to create the enviroment from the `LuaGlobal` constructor, but best practice is to do it over this method. 31 | 32 | see [Tables](04_04_table.md) 33 | 34 | ## `CreateLambda(...)` 35 | 36 | Creates a delegate of lua code without any overhead. 37 | 38 | A delegate, that is generated by this function has no debug information and no environment. *It is not possible* to use global variables or lua function/libraries in the code. Only the clr-Library is useable. 39 | 40 | ```C# 41 | using (Lua l = new Lua()) 42 | { 43 | // Creates the delegate 44 | // the x is optional, if it not given, than the name comes from the delegate-parameter 45 | var f = l.CreateLambda>("f", "return clr.System.Math:Abs(x) * 2", "x"); 46 | Console.WriteLine("f({0}) = {1}", 2, f(2)); 47 | Console.WriteLine("f({0}) = {1}", 2, f(-2)); 48 | 49 | // Creates a delegate with a declaration 50 | // it is possible to set a delegate type (replace the null with the type) 51 | // it is also possible to declare local variables/functions 52 | var f2 = l.CreateLambda("f2", "local Math = clr.System.Math; return Math:Abs(x) * 2;", null, typeof(double), new KeyValuePair("x", typeof(double))); 53 | Console.WriteLine("f2({0}) = {1}", 2, f2.DynamicInvoke(2)); 54 | Console.WriteLine("f2({0}) = {1}", 2, f2.DynamicInvoke(-2)); 55 | } 56 | ``` 57 | 58 | This is a very useful if you need small code blocks, like formulas or simple expressions. 59 | 60 | ## `DefaultDebugEngine` 61 | 62 | Singleton for the a debug engine, that compiles the script in a dynamic assembly with debug information. So, it is possible to retrieve a stack trace from every exception. 63 | The runtime overhead is very low. But on the other hand it consumes a lot memory and the code is not collectable from the garbage collector. 64 | 65 | To have more influence over the memory you have to create a own instance of `LuaStackTraceDebugger`. If this class is collected, all chunks they are associated to debug engine 66 | are also collected. 67 | 68 | The stack trace is added to the Data property of every exception. To retrieve a formatted stack trace use `LuaExceptionData.GetData`. 69 | 70 | ```C# 71 | LuaExceptionDataled = LuaExceptionData.GetData(e); 72 | Console.Write(led.StackTrace); 73 | ``` 74 | 75 | ## `FloatType`, `IntegerType` 76 | 77 | These two properties define the default data type for numbers. 78 | 79 | ## `ParseNumber` 80 | 81 | Parses a number like `tonumber`. 82 | 83 | ## `StandardPackagesPaths`, `StandardPackagesPath` 84 | 85 | The global package search paths. As an array or a `;` seperated list. 86 | 87 | ## `Version` 88 | 89 | Returns the current version of NeoLua. 90 | 91 | ## `void Clear()` 92 | 93 | Clears the dynamic binding rules. 94 | 95 | ## `void DumpRuleCaches(...)` 96 | 97 | Dumps all cached rules of this script engine. This method is only for debug proposes and might be removed in later version. -------------------------------------------------------------------------------- /doc/04_03_chunk.md: -------------------------------------------------------------------------------- 1 | # Chunks 2 | 3 | The lua script engine compiles methods, they are encapsled in a chunk (`LuaChunk`). It is 4 | possible to call the method direct, but it is easier to use the `DoChunk`, `Run` (or `dochunk`) method 5 | of the environment. 6 | 7 | ## `LuaResult Run(LuaTable env, object[] callArgs)` 8 | 9 | Executes the chunk on the given environment. 10 | 11 | ## `Lua Lua { get; }` 12 | 13 | The associated lua script engine. 14 | 15 | ## `string ChunkName { get; }` 16 | 17 | The name of the compiled chunk. It is normally the filename without the extension. 18 | 19 | ## `bool IsCompiled { get; }` 20 | 21 | Is the chunk compiled and executable. 22 | 23 | ## `bool HasDebugInfo { get; }` 24 | 25 | Is the chunk compiled with debug info. If this value is true, it is able to build a stack trace for exceptions within the chunk. 26 | 27 | ## `MethodInfo Method { get; }` 28 | 29 | Access to the compiled chunk and it's declaration. 30 | 31 | ## `int Size { get; }` 32 | 33 | Get's the IL-size. 34 | -------------------------------------------------------------------------------- /doc/04_04_table.md: -------------------------------------------------------------------------------- 1 | # LuaTable 2 | 3 | The `LuaTable`is the most important type of Lua. It is also implemented with an dynamic 4 | interface for an easy use in the host application and the script, too. 5 | 6 | The lua environment (`LuaGlobal`, `LuaGlobalPortable`) is a sub class of the lua table. It holds 7 | the basic environment (global variables, basic functions, packages) of 8 | the lua script. All chunks (except Lambda's) run on environment and manipulate them. 9 | 10 | ## Create a environment 11 | 12 | To create a environment you have to call the `CreateEnvironment` function of the script engine. 13 | 14 | ```C# 15 | using (Lua l = new Lua()) 16 | { 17 | var g = l.CreateEnvironment(); 18 | dynamic dg = g; 19 | } 20 | ``` 21 | 22 | In all examples `l` is a script engine and `g` is a environment (`dg` is the dynamic environment). 23 | 24 | ## Execute script 25 | 26 | To execute a single script on an environment you have to call `DoChunk`. Every script returns a `LuaResult`. If there is no return-command in the script, the result is empty. 27 | 28 | ```C# 29 | LuaResult r = g.DoChunk("return 2", "test.lua"); 30 | Console.WriteLine(r[0]); 31 | ``` 32 | 33 | It is also possible to define parameters for a script. 34 | 35 | ```C# 36 | LuaResult r = g.DoChunk("return a + b", "test.lua", 37 | new KeyValuePair("a", 2), 38 | new KeyValuePair("b", 4)); 39 | Console.WriteLine(r[0]); 40 | ``` 41 | 42 | Or run precompiled scripts more than one time. 43 | 44 | ```C# 45 | var c = l.CompileChunk("return b * 2", "test.lua", false, new KeyValuePair("b", typeof(int))); 46 | Console.WriteLine(g.DoChunk(c, 2)[0]); 47 | Console.WriteLine(g.DoChunk(c, 3)[0]); 48 | Console.WriteLine(g.DoChunk(c, 4)[0]); 49 | ``` 50 | 51 | ## Dynamic environment 52 | 53 | The environment exposes all functionality, that you have in a lua script as an dynamic interface. Use the functions, that you know from lua script. 54 | 55 | ```C# 56 | LuaResult r = dg.dochunk("return 2", "test.lua"); 57 | Console.WriteLine(r[0]); 58 | ``` 59 | 60 | The same with the dynamic interface. 61 | 62 | ```C# 63 | dynamic dr = dg.dochunk("return a + b", "test.lua", "a", 2, "b", 4); 64 | Console.WriteLine((int)dr); 65 | ``` 66 | 67 | And with an argument. 68 | 69 | ```C# 70 | var c = l.CompileChunk("return b * 2", "test.lua", false, new KeyValuePair("b", typeof(int))); 71 | Console.WriteLine(dg.dochunk(c, 2)[0]); 72 | Console.WriteLine(dg.dochunk(c, 3)[0]); 73 | Console.WriteLine(dg.dochunk(c, 4)[0]); 74 | ``` 75 | 76 | ## Member/Variables 77 | 78 | Define or access variables on the environment or tables. 79 | 80 | ```C# 81 | dg.a = 2; // dynamic way to set a variable 82 | g["b"] = 4; // explicit way to access variable 83 | g.DoChunk("c = a + b", "test.lua"); 84 | Console.WriteLine(dg.c); 85 | Console.WriteLine(g["c"]); 86 | ``` 87 | 88 | Define or access a lua table. 89 | 90 | ```C# 91 | dynamic dg = l.CreateEnvironment(); 92 | dg.t = new LuaTable(); -- create global variable t 93 | dg.t.a = 2; -- create a member a on table t 94 | dg.t.b = 4; 95 | dg.dochunk("t.c = t.a + t.b", "test.lua"); 96 | Console.WriteLine(dg.t.c); 97 | ``` 98 | 99 | ## Index access 100 | 101 | It is also easy to work with indices. 102 | 103 | ```C# 104 | dynamic dg = l.CreateEnvironment(); 105 | dg.t = new LuaTable(); 106 | dg.t[0] = 2; 107 | dg.t[1] = 4; 108 | dg.dochunk("t[2] = t[0] + t[1]", "test.lua"); 109 | Console.WriteLine(dg.t[2]); 110 | ``` 111 | 112 | ## Define/call functions 113 | 114 | ```C# 115 | dg.myadd = new Func((a, b) => a + b); // define a new function in c# 116 | dg.dochunk("function Add(a, b) return myadd(a, b) end;", "test.lua"); // define a new function in lua that calls the c# function 117 | 118 | Console.WriteLine((int)dg.Add(2, 4)); //call the lua function 119 | 120 | var f = (Func)dg.Add; // get the lua function 121 | Console.WriteLine(f(2, 4).ToInt32()); 122 | ``` 123 | 124 | Is there no result defined. Lua always let return functions a LuaResult. 125 | 126 | But it also possible to give a explicit definition. 127 | 128 | ```C# 129 | dg.myadd = new Func((a, b) => a + b); 130 | dg.dochunk("function Add(a : int, b : int) : int return myadd(a, b) end;", "test.lua"); 131 | 132 | Console.WriteLine((int)dg.Add(2, 4)); 133 | 134 | var f = (Func)dg.Add; 135 | Console.WriteLine(f(2, 4)); 136 | ``` 137 | 138 | ## Declaring Methods in the host application 139 | 140 | The next example define three members. a, b are members, they are holding 141 | a ordinary integer. And add is holding a function, but this definition is not 142 | a method. Because if you try to call the function like a method in e.g. c#, 143 | it will throw a NullReferenceException. You must always pass the table as a 144 | first parameter to it. To declare a real method, you have to call the explicit 145 | method DefineMethod. 146 | 147 | Lua don't care about the difference, but c# or VB.NET knows it. 148 | 149 | ```C# 150 | dg.t = new LuaTable(); 151 | dg.t.a = 2; 152 | dg.t.b = 4; 153 | dg.t.add = new Func(self => 154 | { 155 | return self.a + self.b; 156 | }); 157 | ((LuaTable)dg.t).DefineMethod("add2", (Delegate)dg.t.add); 158 | 159 | Console.WriteLine(dg.dochunk("return t:add()", "test.lua")[0]); 160 | Console.WriteLine(dg.dochunk("return t:add2()", "test.lua")[0]); 161 | Console.WriteLine(dg.t.add(dg.t)); 162 | Console.WriteLine(dg.t.add2()); 163 | ``` 164 | 165 | # Declaring methods in Lua 166 | 167 | * `add` is a normal function, created from a delegate. 168 | * `add1` is declared as a function. 169 | * `add2` is a method, that is created from a lambda. Becareful a lambda definition doesn't know anything about the concept of methods, so you have to declare the self parameter. 170 | * `add3` shows a method declaration. 171 | 172 | ```C# 173 | LuaResult r = dg.dochunk("t = { a = 2, b = 4 };" + 174 | "t.add = function(self)" + 175 | " return self.a + self.b;" + 176 | "end;" + 177 | "function t.add1(self)" + 178 | " return self.a + self.b;" + 179 | "end;" + 180 | "t:add2 = function (self)" + 181 | " return self.a + self.b;" + 182 | "end;" + 183 | "function t:add3()" + 184 | " return self.a + self.b;" + 185 | "end;" + 186 | "return t:add(), t:add2(), t:add3(), t.add(t), t.add2(t), t.add3(t);", 187 | "test.lua"); 188 | Console.WriteLine(r[0]); 189 | Console.WriteLine(r[1]); 190 | Console.WriteLine(r[2]); 191 | Console.WriteLine(r[3]); 192 | Console.WriteLine(r[4]); 193 | Console.WriteLine(r[5]); 194 | Console.WriteLine(dg.t.add(dg.t)[0]); 195 | Console.WriteLine(dg.t.add2()[0]); 196 | Console.WriteLine(dg.t.add3()[0]); 197 | ``` 198 | 199 | ## Classes/Objects 200 | 201 | To create a class you have to write a function, that creates a new object. The function is by definition the class and the result of the function is the object. 202 | 203 | ```C# 204 | dg.dochunk("function classA()" + 205 | " local c = { sum = 0 };" + 206 | " function c:add(a)" + 207 | " self.sum = self.sum + a;" + 208 | " end;" + 209 | " return c;" + 210 | "end;", "classA.lua"); 211 | 212 | dynamic o = dg.classA()[0]; 213 | o.add(1); 214 | o.add(2); 215 | o.add(3); 216 | Console.WriteLine(o.sum); 217 | ``` 218 | 219 | ## Serialize/Deserialize to a Lua Script Object Notation (Lson) 220 | 221 | To create a string representation of a `table` use the `ToLson` function. To reparse the string use `FromLson`. 222 | 223 | ```Lua 224 | local str = table.ToLson{ 225 | a = 42, 226 | 23 227 | }; 228 | 229 | local t = table.FromLson(str); 230 | ``` 231 | 232 | The content of the variable `str` should be look like: 233 | ``` 234 | { 235 | a = 42, 236 | 23 237 | } 238 | ``` 239 | 240 | If you do not want the indentation set the secound parameter to `false`, 241 | 242 | ```Lua 243 | local str = table.ToLson({ 244 | a = 42, 245 | 23 246 | }, false); 247 | ``` 248 | 249 | The result will be: 250 | ``` 251 | {a=42,23} 252 | ``` 253 | 254 | If you want to change the indentation set the thrid parameter to an pattern. 255 | ```Lua 256 | local str = table.ToLson({ 257 | a = 42, 258 | 23 259 | }, true, " "); 260 | ``` 261 | 262 | Result: 263 | ``` 264 | { 265 | a = 42, 266 | 23 267 | } 268 | ``` 269 | 270 | Types supported are the primitive type (e.g. `int`, `long `,`string`, `bool`, `single`, `double`, ...) and `Guid`, `DateTime`, `char[]`. 271 | -------------------------------------------------------------------------------- /doc/05_01_clr.md: -------------------------------------------------------------------------------- 1 | # clr Library (gateway to .net) 2 | 3 | ## Getting started 4 | 5 | `clr` is a package to access .net framework types and namespaces. The package is 6 | implemented in dynamic class `LuaType`, binds the calls to the host application 7 | or the .net framework classes. 8 | 9 | NeoLua supports static methods, instance methods, overloaded methods, constructors, properties, 10 | types, sub types or events. 11 | 12 | ```Lua 13 | local sys = clr.System; 14 | ``` 15 | Creates a dynamic type instance for the namespance system and assigns this new type 16 | to the local variable sys. So the both following calls are equalent. 17 | 18 | ```Lua 19 | local StringBuilder = sys.Text.StringBuilder; 20 | local StringBuilder1 = clr.System.Text.StringBuilder; -- same result 21 | ``` 22 | 23 | Use this variable like the using in .net to access the type StringBuilder. 24 | 25 | To create a new object from the type call the type like a function. This 26 | will invoke the constructor. 27 | 28 | ```Lua 29 | local sb = StringBuilder('text'); 30 | local sb1 = clr.System.Text.StringBuilder('test'); -- same result 31 | ``` 32 | 33 | If the type is generic use the index access to create a non generic class first. 34 | 35 | ```Lua 36 | local lstObject = clr.System.Collections.Generic.List[clr.System.Object](); 37 | local ListGeneric = clr.System.Collections.Generic.List; 38 | local lstString = ListGeneric[clr.System.String](); 39 | local ListStringType = ListGeneric[clr.System.String]; 40 | local lstString2 = ListStringType(); 41 | ``` 42 | 43 | But the best way to short cut types is to use the `const` keyword. Because it creates no runtime overhead, it is only known during compile time. Becareful, no clr is needed. 44 | 45 | ```Lua 46 | const ListOfObjects typeof System.Collections.Generic.List[System.Object]; 47 | ``` 48 | 49 | The clr package is a "build in" package, so it is useable in Lua-Lambda's. 50 | 51 | ```C# 52 | using (Lua l = new Lua()) 53 | { 54 | var f = l.CreateLambda>("f", "return clr.System.Math:Abs(x) * 2", "x"); 55 | Console.WriteLine("f({0}) = {1}", 2, f(2)); 56 | Console.WriteLine("f({0}) = {1}", -2, f(-2)); 57 | 58 | var f2 = l.CreateLambda("f2", "local Math = clr.System.Math; return Math:Abs(x) * 2;", 59 | null, typeof(double), new KeyValuePair("x", typeof(double))); 60 | Console.WriteLine("f2({0}) = {1}", 2, f2.DynamicInvoke(2)); 61 | Console.WriteLine("f2({0}) = {1}", -2, f2.DynamicInvoke(-2)); 62 | ``` 63 | 64 | ###### Example for StringBuilder 65 | 66 | ```Lua 67 | local sys = clr.System; 68 | local sb = sys.Text.StringBuilder(); 69 | sb:Append('Hallo '):Append('Welt!'); 70 | return sb:ToString(); 71 | ``` 72 | 73 | If you combine this with explict typing, the parser will emit no dynamic calls at all and the runtime of this script is the same like e.g. a C# method. 74 | 75 | ```Lua 76 | const StringBuilder typeof System.Text.StringBuilder(); 77 | local sb : StringBuilder = StringBuilder(); 78 | sb:Append('Hallo '):Append('Welt!'); 79 | return sb:ToString(); 80 | ``` 81 | 82 | ###### Example to work with List's 83 | 84 | ```Lua 85 | local lst = clr.System.Collections.Generic.List[clr.System.Object](); 86 | 87 | lst:Add(1); 88 | lst:Add(2); 89 | lst:Add("String"); 90 | 91 | print("Enum:"); 92 | foreach a in lst do 93 | print(a); 94 | end; 95 | 96 | print("Index:"); 97 | for i = 0,lst.Count-1,1 do 98 | print(i .. ": " .. lst[i]); 99 | end; 100 | 101 | return lst.Count; 102 | ``` 103 | 104 | ## Static methods/Contructors 105 | 106 | Call static methods or contructors direct on the type with the member call. It is also possible to get the reference to the member. 107 | 108 | ###### Example static method 109 | 110 | ```Lua 111 | const Env typeof System.Environment; 112 | print(Env:GetEnvironmentVariable("TEMP")); 113 | local getEnv = Env.GetEnvironmentVariable; -- creates a new object 114 | print(getEnv("TEMP")); 115 | ``` 116 | 117 | ###### Example contructors 118 | 119 | ```Lua 120 | const StringBuilder typeof System.Text.StringBuilder; 121 | local sb : StringBuilder = StringBuilder("Hello "); 122 | ``` 123 | 124 | ###### Example mapping in host application 125 | 126 | Besides using Lua to access framework types and namespace you can also map these in the host application like this: 127 | 128 | ```C# 129 | using (Lua l = new Lua()) 130 | { 131 | var g = l.CreateEnvironment(); 132 | dynamic dg = g; 133 | 134 | dg.customTable = new LuaTable(); 135 | dg.customTable.env = LuaType.GetType(typeof(System.Environment)); 136 | } 137 | ``` 138 | 139 | ```Lua 140 | print(customTable.env.GetEnvironmentVariable("TEMP")); 141 | ``` 142 | 143 | ## Instance methods 144 | 145 | Methods can also called through a member call or you can get the reference to the member. 146 | 147 | ```Lua 148 | const StringBuilder typeof System.Text.StringBuilder; 149 | local sb : StringBuilder = StringBuilder("Hello "); 150 | sb:Append("World!"); 151 | print(sb:ToString()); 152 | local app = sb.Append; -- create a new object 153 | app(" What's"); 154 | app(" up"); 155 | app("!"); 156 | print(sb.ToString()); 157 | ``` 158 | 159 | ## Overloaded methods 160 | 161 | If you call a method with overloads throw the member call NeoLua will try to find the correct overload by the given parameters. 162 | 163 | ```Lua 164 | console.WriteLine("Number: {0}", 23); -- chooses the (string, arg) overload 165 | ``` 166 | 167 | If you assign the member of overloaded method to a variable a object will be created. 168 | 169 | ```Lua 170 | local writeLine = console.WriteLine; -- create a object for the method 171 | writeLine("Number: {0}", 23); -- chooses the (string, arg) overload 172 | local writeLine1 = writeLine[clr.System.String, clr.System.Object]; -- create a reference to a special overload 173 | writeLine1("Number: {0}", 23); 174 | ``` 175 | 176 | ## Properties 177 | 178 | ###### Access static properties: 179 | 180 | ```Lua 181 | print(clr.System.Environment.MachineName); 182 | ``` 183 | ###### Access properties: 184 | 185 | ```Lua 186 | const StringBuilder typeof System.Text.StringBuilder; 187 | local sb : StringBuilder = StringBuilder("Hello "); 188 | return sb.Length; 189 | ``` 190 | 191 | ## Types/Subtypes 192 | 193 | To get the .net type you have tree ways. 194 | 195 | ###### Call the virtual `GetType` method 196 | 197 | ```Lua 198 | return clr.System.Environment:GetType(); 199 | ``` 200 | 201 | ###### Use a explicit cast 202 | 203 | ```Lua 204 | return cast(type, clr.System.Environment); 205 | ``` 206 | 207 | ###### .net `GetType` of the instance 208 | 209 | ```Lua 210 | const StringBuilder typeof System.Text.StringBuilder; 211 | local sb = StringBuilder("Hello "); 212 | return sb:GetType(); 213 | ``` 214 | 215 | ## Array's 216 | 217 | The example creates a array with the specified length. 218 | 219 | ```Lua 220 | local a : int[] = clr.System.Int32[3]; -- int is not a identifier 221 | a[0] = 23; 222 | a[1] = 42; 223 | a[2] = 256; 224 | return a[0] + a[1] + a[2]; 225 | ``` 226 | 227 | The example creates a array with the values. 228 | 229 | ```Lua 230 | const int typeof System.Int32; -- declare the identifier 231 | local a : int[] = int[](23, 42, 256); 232 | return a[0] + a[1] + a[2]; 233 | ``` 234 | 235 | Also multidimensional array's are supported. Because of limitations of the array syntax in lua it is not possible to build a type by syntax. It is only possible to access the array with dynamic calls. 236 | 237 | ```Lua 238 | const int typeof System.Int32; -- declare the identifier 239 | local a = int[2, 2]; 240 | a[0,0] = 23; 241 | a[1,1] = 42; 242 | return a[0,0] + a[1,1]; 243 | ``` 244 | 245 | Becareful, .net array's are zero based, and lua table indexes are one based. 246 | 247 | ## Events 248 | 249 | Events get two new virtual members to add or remove methods of the event. It is important, that the signatures must fit together. 250 | 251 | ```C# 252 | public class MyClass 253 | { 254 | public event Action EventTest; 255 | } 256 | ``` 257 | 258 | ```Lua 259 | myClass.EventTest:add(function() : void print('test'); end); 260 | ``` 261 | 262 | ## Extension methods 263 | 264 | If you want use extension methods on the clr types in a lua script, you have to register them. They are not resolved automaticly due performance reasons. 265 | 266 | To call the lua `sub` method I registered the string library first. 267 | ```C# 268 | LuaType.RegisterTypeExtension(typeof(LuaLibraryString)); 269 | ``` 270 | 271 | That is the reason why you can call 272 | ```Lua 273 | return "test":sub(2, 2); 274 | ``` 275 | in a script. So, it is possible to extent .net types/classes for a lua a script. 276 | 277 | It is also possible to call this function from a lua script. 278 | ```Lua 279 | clr.Neo.IronLua.LuaType:RegisterTypeExtension(clr.Some.Extension.Type); 280 | ``` 281 | 282 | ## Disabling clr access 283 | 284 | If you want to disable access to the clr library, you can do so by setting `ClrEnabled` to false in the compile options. 285 | ```C# 286 | using (var l = new Lua()) 287 | { 288 | var g = l.CreateEnvironment(); 289 | g.DefaultCompileOptions = new LuaCompileOptions() 290 | { 291 | ClrEnabled = false 292 | }; 293 | // With ClrEnabled set to false, this should return false; 294 | g.DoChunk("print('Clr Access is: ' .. (type(clr) == type(nil) and 'Disabled' or 'Enabled'));", "test.lua"); 295 | } 296 | ``` -------------------------------------------------------------------------------- /doc/05_02_extent.md: -------------------------------------------------------------------------------- 1 | # Packages (!todo!) 2 | 3 | It is possible to add more packages to the environment. There are two ways to add packages. Static packages and dynamic packages. 4 | 5 | Static Packages are basically static classes. The static members will be available in Lua. 6 | 7 | Restrictions: 8 | 9 | * No overload allowed. 10 | * No Instance members allowed. 11 | 12 | 13 | Example declaration: 14 | 15 | ```C# 16 | public static class Test 17 | { 18 | public static int add(int a, int b) 19 | { 20 | return a + b; 21 | } 22 | } 23 | ``` 24 | 25 | Example register: 26 | 27 | ```C# 28 | LuaGlobal g = ... 29 | g.RegisterPackage("test", typeof(Test)); 30 | ``` 31 | 32 | Example usage: 33 | 34 | ```Lua 35 | return test.add(1, 2); 36 | ``` 37 | 38 | For dynamic packages you have to implement IDynamicMetaObjectProvider. More information can 39 | be find under http://dlr.codeplex.com/documentation (library-authors-introduction.pdf) 40 | 41 | For registration of dynamic package, just create a global variable. 42 | 43 | # Extent the global namespace (LuaGlobal) 44 | 45 | The easiest way to add new functions or members to the Lua environment is to add a global 46 | variable. It is also the only way to override the standard implementation of the function. If 47 | you want the standard back, just set the global to nil/null. 48 | 49 | ```Lua 50 | -- change print 51 | print = function (...) 52 | -- fancy new print 53 | end; 54 | -- restore print 55 | print = nil; 56 | ``` 57 | 58 | It is also possible to create your own Lua environment. For this you have to subclass the standard environment LuaGlobal. To extent your environment add a private function to the class and mark it with LuaMemberAttribute. 59 | 60 | Example: 61 | 62 | ```C# 63 | [LuaMember("rawset")] 64 | private LuaTableLuaRawSet(LuaTablet, objectindex, objectvalue) 65 | ``` 66 | 67 | A third way is to override GetMemberAccess and return a expression and restriction for the member. -------------------------------------------------------------------------------- /doc/05_03_debug.md: -------------------------------------------------------------------------------- 1 | # Debugging 2 | 3 | It is possible to implement your own trace line debugger. 4 | 5 | Inherit from `LuaTraceLineDebugger` and pass a instance of this class to the `CompileChunk` debug argument. -------------------------------------------------------------------------------- /doc/07_neocmd.md: -------------------------------------------------------------------------------- 1 | # NeoCmd 2 | 3 | ## Usage 4 | 5 | NeoCmd is a console application that is able to executes scripts. 6 | 7 | Type in the lua code that you want to execute. If you let one line blank, that code will be executed. 8 | 9 | Start the line with a colon to execute a command, like `:q' for exit. 10 | 11 | ## Commands 12 | 13 | | Command | Description | 14 | |------------|-------------| 15 | | `:q` | Exit the application. | 16 | | `:h` | Show the command list. | 17 | | `:list` | Lists all global variables. | 18 | | `:load` | Loads the lua-script from a file. | 19 | | `:debugoff` | Tell the compiler to emit no debug informations. | 20 | | `:debugon` | Let the compiler emit debug informations. | 21 | | `:debugtracLet` | the compiler emit trace line functionality. | 22 | | `:c` | Clears the current script buffer. | 23 | | `:env` | Create a fresh environment. | 24 | | `:cache` | Shows the content of the binder cache. | 25 | 26 | ## Command line 27 | 28 | It is possible to load a script during start up. 29 | 30 | ``` 31 | NeoCmd.exe [-debugoff | -debugon | -debugtrace ] [Scriptfile] ... 32 | ``` -------------------------------------------------------------------------------- /doc/Implementation.xlsm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/doc/Implementation.xlsm -------------------------------------------------------------------------------- /doc/imgs/Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/doc/imgs/Image.png -------------------------------------------------------------------------------- /doc/imgs/done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/doc/imgs/done.png -------------------------------------------------------------------------------- /doc/imgs/noco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/doc/imgs/noco.png -------------------------------------------------------------------------------- /doc/imgs/noti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neolithos/neolua/28134b4dbcf7582a8945e585d2e20ecde6c0ee60/doc/imgs/noti.png --------------------------------------------------------------------------------