diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index cb3c971b..42115567 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -2,9 +2,9 @@ name: .NET on: push: - branches: [ librelancer ] + branches: [ main ] pull_request: - branches: [ librelancer ] + branches: [ main ] jobs: build: @@ -16,7 +16,9 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v2 with: - dotnet-version: 6.0.x + dotnet-version: | + 8.0.x + 10.0.x - name: Restore dependencies working-directory: ./src run: dotnet restore diff --git a/AUTHORS b/AUTHORS index e7c607de..a5a5f6bb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,5 +1,5 @@ -# This is the list of MoonSharp's significant contributors. +# This is the list of WattleScript's significant contributors. # # This does not necessarily list everyone who has contributed code, # especially since many employees of one corporation may be contributing. diff --git a/LICENSE b/LICENSE index 5b1726e3..9f90d10f 100755 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2014-2022 The MoonSharp Authors, as shown by the AUTHORS file. +Copyright (c) 2014-2025 The WattleScript Authors, as shown by the AUTHORS file. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -30,5 +30,3 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Parts of the string library are based on the KopiLua project (https://github.com/NLua/KopiLua) Copyright (c) 2012 LoDC - -The MoonSharp icon is (c) Isaac, 2014-2015 diff --git a/README.md b/README.md index b9ccb335..da52dfaf 100755 --- a/README.md +++ b/README.md @@ -1,82 +1,35 @@ -MoonSharp: Librelancer Branch -* This only contains a subset of the MoonSharp project for .Net Core 3.1 -* See upstream at https://github.com/moonsharp-devs/moonsharp +WattleScript +https://wattlescript.github.io/ -MoonSharp [![Build Status](https://travis-ci.org/xanathar/moonsharp.svg?branch=master)](https://travis-ci.org/xanathar/moonsharp) [![Build Status](https://img.shields.io/nuget/v/MoonSharp.svg)](https://www.nuget.org/packages/MoonSharp/) -========= -http://www.moonsharp.org +
+WattleScript is a scripting engine written in C# for runtimes supporting .NET Standard 2.0 and newer. (.NET 4.7.2+, .NET Core 3.1+). It is a dual-language environment, providing support for Lua 5.2 code as well as its own language, Wattle. -A complete Lua solution written entirely in C# for the .NET, Mono, Xamarin and Unity3D platforms. +Using WattleScript is as easy as: -Features: -* 99% compatible with Lua 5.2 (with the only unsupported feature being weak tables support) -* Support for metalua style anonymous functions (lambda-style) -* Easy to use API -* **Debugger** support for Visual Studio Code (PCL targets not supported) -* Remote debugger accessible with a web browser and Flash (PCL targets not supported) -* Runs on .NET 3.5, .NET 4.x, .NET Core, Mono, Xamarin and Unity3D -* Runs on Ahead-of-time platforms like iOS -* Runs on IL2CPP converted code -* Runs on platforms requiring a .NET 4.x portable class library (e.g. Windows Phone) -* No external dependencies, implemented in as few targets as possible -* Easy and performant interop with CLR objects, with runtime code generation where supported -* Interop with methods, extension methods, overloads, fields, properties and indexers supported -* Support for the complete Lua standard library with very few exceptions (mostly located on the 'debug' module) and a few extensions (in the string library, mostly) -* Async methods for .NET 4.x targets -* Supports dumping/loading bytecode for obfuscation and quicker parsing at runtime -* An embedded JSON parser (with no dependencies) to convert between JSON and Lua tables -* Easy opt-out of Lua standard library modules to sandbox what scripts can access -* Easy to use error handling (script errors are exceptions) -* Support for coroutines, including invocation of coroutines as C# iterators -* REPL interpreter, plus facilities to easily implement your own REPL in few lines of code -* Complete XML help, and walkthroughs on http://www.moonsharp.org - -For highlights on differences between MoonSharp and standard Lua, see http://www.moonsharp.org/moonluadifferences.html - -Please see http://www.moonsharp.org for downloads, infos, tutorials, etc. - - -**License** - -The program and libraries are released under a 3-clause BSD license - see the license section. - -Parts of the string library are based on the KopiLua project (https://github.com/NLua/KopiLua). -Debugger icons are from the Eclipse project (https://www.eclipse.org/). - - -**Usage** - -Use of the library is easy as: - -```C# -double MoonSharpFactorial() -{ - string script = @" - -- defines a factorial function - function fact (n) - if (n == 0) then - return 1 - else - return n*fact(n - 1) - end - end - - return fact(5)"; - - DynValue res = Script.RunString(script); - return res.Number; -} +```cs +var script = new Script(); +script.DoString("print('Hello World!')"); ``` -For more in-depth tutorials, samples, etc. please refer to http://www.moonsharp.org/getting_started.html - - - - +WattleScript is based off the tried and tested [MoonSharp](https://moonsharp.org) project, inheriting its VM design and test suite. The design focuses on easy and fast interop with .NET objects and functions. +### Features +* [Wattle](https://wattlescript.github.io/about_wattle) scripting language. +* Lua mode 99% compatible with Lua 5.2, differences documented [here](https://wattlescript.github.io/lua_differences). +* Easily configured sandbox for safe execution of untrusted scripts. +* Minimal garbage generation at runtime +* No external dependencies +* Easy and performant interop with CLR objects, with runtime code generation where supported +* Source Generator for AOT interop. +* Support for awaiting on returned values +* Supports dumping/loading bytecode +* Support for the complete Lua standard library with very few exceptions (mostly located in the `debug` module). +* `json` module for loading json into tables safely at runtime. +### License +WattleScript is licensed under the 3-clause BSD License. See [LICENSE](https://github.com/WattleScript/wattlescript/blob/main/LICENSE) for details. diff --git a/src/MoonSharp.Hardwire/IdGen.cs b/src/MoonSharp.Hardwire/IdGen.cs deleted file mode 100644 index 64d7e691..00000000 --- a/src/MoonSharp.Hardwire/IdGen.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Numerics; -using System.Text; -using System.Security.Cryptography; - -namespace MoonSharp.Hardwire -{ - static class IdGen - { - private const string ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; - public static string Create(string str) - { - using (MD5 md5Hash = MD5.Create()) - { - var bLen = BitConverter.GetBytes((ushort) str.Length); - byte[] bytes = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str)); - return Encode(new BigInteger(bLen.Concat(bytes).Append((byte)0).ToArray())); - } - } - static string Encode(BigInteger number) - { - if(number < 0) - throw new ArgumentException(); - var builder = new StringBuilder(); - var divisor = new BigInteger(ALPHABET.Length); - while (number > 0) - { - number = BigInteger.DivRem(number, divisor, out var rem); - builder.Append(ALPHABET[(int) rem]); - } - return new string(builder.ToString().Reverse().ToArray()); - } - } -} \ No newline at end of file diff --git a/src/MoonSharp.Hardwire/Utils/GeneratorUtilities.cs b/src/MoonSharp.Hardwire/Utils/GeneratorUtilities.cs deleted file mode 100644 index 85e03263..00000000 --- a/src/MoonSharp.Hardwire/Utils/GeneratorUtilities.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.CodeDom; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using MoonSharp.Interpreter; -using MoonSharp.Interpreter.Interop.BasicDescriptors; -using MoonSharp.Interpreter.Interop.StandardDescriptors.HardwiredDescriptors; - -namespace MoonSharp.Hardwire.Utils -{ - public class GeneratorUtilities - { - - - - - } -} diff --git a/src/MoonSharp.HardwireGen/IdGen.cs b/src/MoonSharp.HardwireGen/IdGen.cs deleted file mode 100644 index 823a0c5a..00000000 --- a/src/MoonSharp.HardwireGen/IdGen.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Numerics; -using System.Text; -using System.Security.Cryptography; - -namespace MoonSharp.HardwireGen -{ - static class IdGen - { - private const string ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_"; - public static string Create(string str) - { - using (MD5 md5Hash = MD5.Create()) - { - var bLen = BitConverter.GetBytes((ushort) str.Length); - byte[] bytes = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(str)); - return Encode(new BigInteger(bLen.Concat(bytes).Append((byte)0).ToArray())); - } - } - static string Encode(BigInteger number) - { - if(number < 0) - throw new ArgumentException(); - var builder = new StringBuilder(); - var divisor = new BigInteger(ALPHABET.Length); - while (number > 0) - { - number = BigInteger.DivRem(number, divisor, out var rem); - builder.Append(ALPHABET[(int) rem]); - } - return new string(builder.ToString().Reverse().ToArray()); - } - } -} \ No newline at end of file diff --git a/src/MoonSharp.HardwireGen/MoonSharp.HardwireGen.csproj b/src/MoonSharp.HardwireGen/MoonSharp.HardwireGen.csproj deleted file mode 100644 index a5987d27..00000000 --- a/src/MoonSharp.HardwireGen/MoonSharp.HardwireGen.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - netstandard2.0 - 9 - - - - - - diff --git a/src/MoonSharp.HardwireGen/SourceGenerator.ClassNames.cs b/src/MoonSharp.HardwireGen/SourceGenerator.ClassNames.cs deleted file mode 100644 index 001b6d8c..00000000 --- a/src/MoonSharp.HardwireGen/SourceGenerator.ClassNames.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace MoonSharp.HardwireGen -{ - public partial class HardwireSourceGenerator - { - private const string CLS_USERDATA = - "MoonSharp.Interpreter.Interop.StandardDescriptors.HardwiredDescriptors.HardwiredUserDataDescriptor"; - - private const string CLS_OVERLOAD = "MoonSharp.Interpreter.Interop.OverloadedMethodMemberDescriptor"; - - private const string CLS_OVERLOAD_MEMBER = - "MoonSharp.Interpreter.Interop.BasicDescriptors.IOverloadableMemberDescriptor"; - - private const string CLS_PROP_FIELD = - "MoonSharp.Interpreter.Interop.StandardDescriptors.HardwiredDescriptors.HardwiredMemberDescriptor"; - - private const string CLS_METHOD = - "MoonSharp.Interpreter.Interop.StandardDescriptors.HardwiredDescriptors.HardwiredMethodMemberDescriptor"; - - private const string CLS_PARAMETER = "MoonSharp.Interpreter.Interop.BasicDescriptors.ParameterDescriptor"; - - - } -} \ No newline at end of file diff --git a/src/MoonSharp.HardwireGen/SourceGenerator.cs b/src/MoonSharp.HardwireGen/SourceGenerator.cs deleted file mode 100644 index 8cf6a55e..00000000 --- a/src/MoonSharp.HardwireGen/SourceGenerator.cs +++ /dev/null @@ -1,657 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace MoonSharp.HardwireGen -{ - [Generator] - public partial class HardwireSourceGenerator : ISourceGenerator - { - private static DiagnosticDescriptor ByRefWarning = new("MS1001", - "ByRef parameters can't be generated", - "Method '{0}' has ref/out parameters and won't be described, mark with MoonSharpHiddenAttribute.", - "MoonSharp.HardwireGen", DiagnosticSeverity.Warning, true); - - private static DiagnosticDescriptor NoFilesWarning = new("MS1002", - "AdditionalFiles has no types listed", - "File '{0}' has no additional types listed.", - "MoonSharp.HardwireGen", DiagnosticSeverity.Warning, true); - - private static DiagnosticDescriptor TypeResolveWarning = new("MS1003", - "Type could not be resolved", - "Type '{0}' from AdditionalFile '{1}' could not be resolved.", - "MoonSharp.HardwireGen", DiagnosticSeverity.Warning, true); - - private static DiagnosticDescriptor Timing = new("MS9999", "Generation duration", - "Hardwire generation took '{0}'ms", "MoonSharp.HardwireGen", DiagnosticSeverity.Info, true); - - public void Initialize(GeneratorInitializationContext context) - { - context.RegisterForSyntaxNotifications(() => new UserDataSyntaxReceiver()); - } - - static string Sanitize(string t) - { - return t.Replace(".", "_").Replace(",", "__").Replace("<", "___").Replace(">", "___"); - } - - - private static string[] SkipTypes = - { - "System.Object", "System.Type" - }; - - TypeGenQueue types = new TypeGenQueue(); - private List generatedClasses = new List(); - private HashSet blacklist = new HashSet(); - - static IEnumerable GenericParts(string input) - { - var s = ""; - int bC = 0; - for (int i = 0; i < input.Length; i++) - { - if (input[i] == '<') - bC++; - if (input[i] == '>') - bC--; - if (bC == 0 && input[i] == ',') - { - yield return s; - s = ""; - } - else - { - s += input[i]; - } - } - - if (s != "") - yield return s; - } - - static ITypeSymbol GetTypeFromName(ref GeneratorExecutionContext context, string type) - { - if (string.IsNullOrWhiteSpace(type)) return null; - if (type.Contains("<")) - { - var startIndex = type.IndexOf('<') + 1; - var endIndex = type.LastIndexOf('>'); - if (endIndex == -1) return null; - var generics = type.Substring(startIndex, endIndex - startIndex); - var parts = GenericParts(generics).ToArray(); - var baseName = type.Substring(0, startIndex - 1) + "`" + parts.Length; - INamedTypeSymbol ts = context.Compilation.GetTypeByMetadataName(baseName); - if (ts == null) return null; - ITypeSymbol[] parameters = new ITypeSymbol[parts.Length]; - for (int i = 0; i < parameters.Length; i++) - { - parameters[i] = GetTypeFromName(ref context, parts[i]); - if (parameters[i] == null) return null; - } - - return ts.Construct(parameters); - } - else - { - return context.Compilation.GetTypeByMetadataName(type); - } - } - - void ProcessAdditionalFile(ref GeneratorExecutionContext context, AdditionalText file) - { - ExtraClassList ec; - if ((ec = ExtraClassList.Get(file.Path)) != null) - { - if (ec.ExtraType != null && ec.ExtraType.Length > 0) - { - foreach (var t in ec.ExtraType) - { - var x = t.Trim(); - var ts = GetTypeFromName(ref context, x); - if (ts == null) - { - context.ReportDiagnostic(Diagnostic.Create(TypeResolveWarning, null, x, file.Path)); - } - else - { - types.Enqueue(ts); - } - } - } - else - { - context.ReportDiagnostic(Diagnostic.Create(NoFilesWarning, null, file.Path)); - } - - if (ec.BlacklistType != null && ec.BlacklistType.Length > 0) - { - foreach (var t in ec.BlacklistType) - { - var x = t.Trim(); - var ts = GetTypeFromName(ref context, x); - if (ts == null) - { - context.ReportDiagnostic(Diagnostic.Create(TypeResolveWarning, null, x, file.Path)); - } - else - { - blacklist.Add(ts.TypeName()); - } - } - } - } - } - - public void Execute(GeneratorExecutionContext context) - { - var sw = Stopwatch.StartNew(); - try - { - var receiver = (UserDataSyntaxReceiver) context.SyntaxReceiver; - var name = context.Compilation.Assembly.Name; - if (string.IsNullOrEmpty(name)) - name = IdGen.Create(context.Compilation.Assembly.NamespaceNames.FirstOrDefault() ?? - "_MoonSharp"); - name = "LuaHardwire_" + Sanitize(name); - - foreach (var classDeclaration in receiver.Candidates) - { - var model = context.Compilation.GetSemanticModel(classDeclaration.SyntaxTree, true); - var type = ModelExtensions.GetDeclaredSymbol(model, classDeclaration) as ITypeSymbol; - if (type is null || !IsUserData(type)) - continue; - types.Enqueue(type); - } - - foreach (var file in context.AdditionalFiles) - { - ProcessAdditionalFile(ref context, file); - } - - while (types.Count > 0) - { - TryGenerate(ref context, name, types.Dequeue()); - } - - var writer = new TabbedWriter(); - writer.AppendLine("// "); - writer.Append("partial class ").AppendLine(name); - writer.AppendLine("{").Indent(); - writer.AppendLine("public static void Initialize()"); - writer.AppendLine("{").Indent(); - foreach (var str in generatedClasses) - { - writer.Append("MoonSharp.Interpreter.UserData.RegisterType(new ").Append(str).AppendLine("());"); - } - - writer.UnIndent().AppendLine("}"); - writer.UnIndent().AppendLine("}"); - context.AddSource($"{name}.g.cs", writer.ToString()); - sw.Stop(); - context.ReportDiagnostic(Diagnostic.Create(Timing, null, sw.Elapsed.TotalMilliseconds)); - } - catch (Exception e) - { - sw.Stop(); - throw new Exception(e.Message + "> " + e.StackTrace.Replace('\n', ';')); - } - } - - static bool IsUserData(ITypeSymbol type) - { - return type.GetAttributes() - .Any(a => a.AttributeClass?.ToString() == "MoonSharp.Interpreter.MoonSharpUserDataAttribute"); - } - - static bool IsHidden(ISymbol symbol) - { - foreach (var attr in symbol.GetAttributes()) - { - if (attr.AttributeClass?.ToString() == "MoonSharp.Interpreter.MoonSharpHiddenAttribute") - return true; - if (attr.AttributeClass?.ToString() == "MoonSharp.Interpreter.MoonSharpVisibleAttribute") - { - if (attr.ConstructorArguments[0].Value is false) - return true; - } - } - - return false; - } - - static string TypeName(ITypeSymbol type) - { - return type.ToDisplayString(new SymbolDisplayFormat( - SymbolDisplayGlobalNamespaceStyle.Omitted, - SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, - SymbolDisplayGenericsOptions.IncludeTypeParameters, - miscellaneousOptions: SymbolDisplayMiscellaneousOptions.ExpandNullable - )); - } - - - void TryGenerate(ref GeneratorExecutionContext context, string containingName, ITypeSymbol type) - { - //skip blacklisted - if (blacklist.Any(x => x == type.TypeName())) return; - if (SkipTypes.Any(x => x == type.ToString())) return; - //gen - GenerateCode(ref context, containingName, type); - } - - static bool IsUnsupported(ITypeSymbol type) - { - if (type.IsRefLikeType || type.TypeKind == TypeKind.Pointer || - type.TypeKind == TypeKind.FunctionPointer) return true; - return false; - } - - void GenerateCode(ref GeneratorExecutionContext context, string containingName, ITypeSymbol type) - { - var builder = new TabbedWriter(); - var typeName = TypeName(type); - string classname = "T_" + IdGen.Create(typeName); - generatedClasses.Add(classname); - Dictionary methods = new Dictionary(); - Dictionary fields = new Dictionary(); - builder.AppendLine("// "); - builder.Append("// UserData description for: ").AppendLine(typeName); - - builder.Append("internal partial class ").Append(containingName).AppendLine().AppendLine("{").Indent(); - - builder.Append("public sealed class ").Append(classname).Append(" : ").AppendLine(CLS_USERDATA); - builder.AppendLine("{").Indent(); - - foreach (var m in type.GetPublicMembers()) - { - if (IsHidden(m.symbol)) - { - builder.AppendLine("//Hidden Symbol: " + m.symbol.ToDisplayString()); - continue; - } - - if (m.symbol.IsStatic) continue; - if (m.symbol is IMethodSymbol method) - { - if (method.MethodKind == MethodKind.Ordinary || - (method.MethodKind == MethodKind.Constructor && m.level == 0)) - { - if (method.IsGenericMethod) continue; - bool byref = method.ReturnsByRef || method.ReturnsByRefReadonly; - foreach (var p in method.Parameters) - { - if (p.RefKind == RefKind.Ref || p.RefKind == RefKind.Out || - p.RefKind == RefKind.RefReadOnly) - { - byref = true; - break; - } - } - - bool unsupportedTypes = false; - foreach (var p in method.Parameters) - { - if (IsUnsupported(p.Type)) - { - unsupportedTypes = true; - break; - } - } - - if (unsupportedTypes) continue; - if (byref) - { - if (m.level == 0) - context.ReportDiagnostic(Diagnostic.Create(ByRefWarning, - method.Locations.FirstOrDefault(), method.ToString())); - continue; - } - - if (method.MethodKind == MethodKind.Constructor) - { - if (!methods.ContainsKey("__new")) - methods.Add("__new", new TypeMethod() {Constructor = true}); - methods["__new"].AddMethod(0, method); - } - else - { - if (!methods.ContainsKey(method.Name)) methods.Add(method.Name, new TypeMethod()); - methods[method.Name].AddMethod(m.level, method); - } - } - } - - if (m.symbol is IPropertySymbol property) - { - if (IsUnsupported(property.Type)) continue; - if (property.RefKind == RefKind.Ref) - { - continue; - } - - if (property.IsIndexer) - { - continue; //name is this[] - } - - TypeFieldDesc desc = new TypeFieldDesc() {Type = property.Type}; - if (property.GetMethod != null) - { - desc.Read = true; - var name = "get_" + property.Name; - if (!methods.ContainsKey(name)) - methods.Add(name, new TypeMethod() - { - Property = true, - PropertyName = property.Name - }); - methods[name].SetName(name); - methods[name].AddMethod(m.level, property.GetMethod); - } - if (property.SetMethod != null) - { - desc.Write = true; - var name = "set_" + property.Name; - if (!methods.ContainsKey(name)) - methods.Add(name, new TypeMethod() - { - Property = true, - PropertyName = property.Name, - }); - methods[name].SetName(name); - methods[name].AddMethod(m.level, property.SetMethod); - } - if (!fields.ContainsKey(property.Name)) - fields.Add(property.Name, new TypeField() {Name = property.Name}); - fields[property.Name].Set(m.level, desc); - } - - if (m.symbol is IFieldSymbol field) - { - if (IsUnsupported(field.Type)) continue; - TypeFieldDesc desc = new TypeFieldDesc() {Type = field.Type}; - desc.Read = true; - desc.Write = !field.IsReadOnly; - if (!fields.ContainsKey(field.Name)) fields.Add(field.Name, new TypeField() {Name = field.Name}); - fields[field.Name].Set(m.level, desc); - } - } - - foreach (var m in methods.Values) - { - GenerateMethod(builder, typeName, m); - } - foreach(var f in fields.Values) - { - GenerateField(builder, typeName, f); - } - - //Constructor - builder.Append("internal ").Append(classname).Append("() : base(typeof(").Append(typeName).AppendLine("))"); - builder.AppendLine("{").Indent(); - foreach (var kv in methods) - { - builder.Append("this.AddMember("); - builder.Append(kv.Key.ToLiteral()); - //new OverloadedMethodMemberDescriptor(name, typeof(type), new IOverloadableMemberDescriptor[] { classes }); - builder.Append(", new ").Append(CLS_OVERLOAD).Append(" (").Append(kv.Key.ToLiteral()) - .Append(", typeof(").Append(typeName).Append("), new ").Append(CLS_OVERLOAD_MEMBER) - .AppendLine("[] { "); - builder.Indent(); - for (int i = 0; i < kv.Value.Overloads.Count; i++) - { - builder.Append("new ").Append(kv.Value.ClassName(i)).Append("()"); - if (i + 1 < kv.Value.Overloads.Count) - builder.AppendLine(","); - else - builder.AppendLine(); - } - - builder.UnIndent(); - builder.AppendLine("}));"); - } - foreach(var kv in fields) - { - builder.Append("this.AddMember("); - builder.Append(kv.Key.ToLiteral()); - builder.Append(", "); - builder.Append("new ").Append(kv.Value.ClassName()).AppendLine("());"); - } - - builder.UnIndent().AppendLine("}"); - builder.UnIndent().AppendLine("}"); - builder.UnIndent().AppendLine("}"); - context.AddSource($"{classname}.g.cs", builder.ToString()); - } - - void GenerateField(TabbedWriter builder, string typeName, TypeField f) - { - builder.Append("private sealed class ").Append(f.ClassName()).Append(" : ").AppendLine(CLS_PROP_FIELD); - builder.AppendLine("{").Indent(); - builder.Append("internal ").Append(f.ClassName()).AppendLine("() :"); - var access = 0; - if (f.Desc.Read) access += 1; //CanRead - if (f.Desc.Write) access += 2; //CanWrite - builder.Indent().Append("base(typeof(").Append(f.Desc.Type.TypeName()).Append("),") - .Append(f.Name.ToLiteral()).Append(",false,") - .Append("(MoonSharp.Interpreter.Interop.BasicDescriptors.MemberDescriptorAccess)") - .Append(access.ToString()).AppendLine(")").UnIndent(); - builder.AppendLine("{"); - builder.AppendLine("}"); - if (f.Desc.Read) - { - builder.AppendLine( - "protected override object GetValueImpl(MoonSharp.Interpreter.Script script, object obj) {") - .Indent(); - builder.Append("var self = (").Append(typeName).AppendLine(")obj;"); - builder.Append("return (object)self.").Append(f.Name).AppendLine(";"); - builder.UnIndent().AppendLine("}"); - } - if (f.Desc.Write) - { - builder.AppendLine( - "protected override void SetValueImpl(MoonSharp.Interpreter.Script script, object obj, object value) {") - .Indent(); - builder.Append("var self = (").Append(typeName).AppendLine(")obj;"); - builder.Append("self.").Append(f.Name).Append(" = (").Append(f.Desc.Type.TypeName()).AppendLine(")value;"); - builder.UnIndent().AppendLine("}"); - } - builder.UnIndent().AppendLine("}"); - } - void GenerateMethod(TabbedWriter builder, string typeName, TypeMethod m) - { - for (int i = 0; i < m.Overloads.Count; i++) - { - var method = m.Overloads[i]; - builder.Append("private sealed class ").Append(m.ClassName(i)).Append(" : ").AppendLine(CLS_METHOD); - builder.AppendLine("{").Indent(); - //ctor, add descriptors - builder.Append("internal ").Append(m.ClassName(i)).Append("()"); - builder.AppendLine("{").Indent(); - //funcName, isStatic, ParameterDescriptor[], isExtensionMethod - string isStatic = m.Constructor ? "true" : "false"; - builder.Append("this.Initialize(").Append(m.Name.ToLiteral()).Append($", {isStatic}, new ") - .Append(CLS_PARAMETER).AppendLine("[] {"); - builder.Indent(); - int j = 0; - foreach (var p in method.Parameters) - { - j++; - builder.Append("new ").Append(CLS_PARAMETER).Append("("); - builder.Append(p.Name.ToLiteral()).Append(", "); - builder.Append("typeof(").Append(TypeName(p.Type)).Append("), "); - builder.Append("false, "); //hasDefault - builder.Append("null, "); //default - builder.Append("false, "); //out - builder.Append("false, "); //ref - if (p.IsParams) builder.Append("true"); - else builder.Append("false"); - if (j < method.Parameters.Length) builder.AppendLine("),"); - else builder.AppendLine(")"); - } - - builder.UnIndent().AppendLine("}, false);"); - builder.UnIndent().AppendLine("}"); - //invoke - builder.AppendLine( - "protected override object Invoke(MoonSharp.Interpreter.Script script, object obj, object[] pars, int argscount)"); - builder.AppendLine("{").Indent(); - if (!m.Constructor) - builder.Append("var self = (").Append(typeName).AppendLine(")obj;"); - if (!method.ReturnsVoid && !m.Constructor) - { - builder.Append("return (object)"); - } - - if (!m.Constructor) - { - builder.Append("self."); - builder.Append(m.PropertyName ?? method.Name); - } - else - { - builder.Append("return new "); - builder.Append(typeName); - } - - if (!m.Property) - { - builder.Append("("); - for (int k = 0; k < method.Parameters.Length; k++) - { - builder.Append("(").Append(TypeName(method.Parameters[k].Type)).Append(")"); - builder.Append("pars["); - builder.Append(k.ToString()); - builder.Append("]"); - if (k + 1 < method.Parameters.Length) builder.Append(", "); - } - - builder.AppendLine(");"); - } - else - { - if (method.Parameters.Length > 0) - { - builder.Append(" = (").Append(TypeName(method.Parameters[0].Type)).Append(")pars[0]"); - } - - builder.AppendLine(";"); - } - - if (method.ReturnsVoid && !m.Constructor) builder.AppendLine("return null;"); - builder.UnIndent().AppendLine("}"); - builder.UnIndent().AppendLine("}"); - } - } - - class TypeFieldDesc - { - public ITypeSymbol Type; - public bool Read; - public bool Write; - } - - class TypeField - { - public int CurrLevel = 1000; - public TypeFieldDesc Desc; - public string Name; - - public string ClassName() => "F_" + Name; - public void Set(int level, TypeFieldDesc desc) - { - if (level < CurrLevel) - { - CurrLevel = level; - Desc = desc; - } - } - } - - class TypeMethod - { - public List Overloads = new List(); - public int CurrentLevel = 1000; - public bool Constructor = false; - public bool Property = false; - public string PropertyName = null; - private string _name; - - public void SetName(string n) - { - _name = n; - } - - public string Name => _name ?? (Overloads.Count > 0 ? Overloads[0].Name : ""); - - public string ClassName(int overload) - { - return "M" + overload + "_" + Sanitize(Name); - } - - public override string ToString() - { - if (Overloads.Count < 0) return "[empty]"; - return Overloads[0].Name + " (" + - string.Join(";", Overloads.Select(x => x.ToDisplayString())) + ")"; - } - - public void AddMethod(int level, IMethodSymbol symbol) - { - if (level > CurrentLevel) return; - if (level < CurrentLevel) - { - Overloads = new List(); - CurrentLevel = level; - } - Overloads.Add(symbol); - } - } - } - - public class UserDataSyntaxReceiver : ISyntaxReceiver - { - public List Candidates { get; } = new(); - - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) - { - if (syntaxNode is not AttributeSyntax attribute) - return; - - var name = ExtractName(attribute.Name); - - if (name != "MoonSharpUserData" && name != "MoonSharpUserDataAttribute") - return; - - // "attribute.Parent" is "AttributeListSyntax" - // "attribute.Parent.Parent" is a C# fragment the attribute is applied to - if (attribute.Parent?.Parent is ClassDeclarationSyntax classDeclaration) - Candidates.Add(classDeclaration); - } - - private static string ExtractName(TypeSyntax type) - { - while (type != null) - { - switch (type) - { - case IdentifierNameSyntax ins: - return ins.Identifier.Text; - - case QualifiedNameSyntax qns: - type = qns.Right; - break; - - default: - return null; - } - } - - return null; - } - } -} diff --git a/src/MoonSharp.HardwireGen/TypeGenQueue.cs b/src/MoonSharp.HardwireGen/TypeGenQueue.cs deleted file mode 100644 index 2e67f127..00000000 --- a/src/MoonSharp.HardwireGen/TypeGenQueue.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Collections.Generic; -using Microsoft.CodeAnalysis; - -namespace MoonSharp.HardwireGen -{ - public class TypeGenQueue - { - private HashSet hs = new HashSet(); - private Queue queue = new Queue(); - - public bool Enqueue(ITypeSymbol item) - { - if (hs.Contains(item.TypeName())) return false; - hs.Add(item.TypeName()); - queue.Enqueue(item); - return true; - } - - public int Count => queue.Count; - - public ITypeSymbol Dequeue() => queue.Dequeue(); - } -} \ No newline at end of file diff --git a/src/MoonSharp.Interpreter/AsyncExtensions.cs b/src/MoonSharp.Interpreter/AsyncExtensions.cs deleted file mode 100755 index eb0055c5..00000000 --- a/src/MoonSharp.Interpreter/AsyncExtensions.cs +++ /dev/null @@ -1,421 +0,0 @@ -#if HASDYNAMIC -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using MoonSharp.Interpreter.REPL; - -namespace MoonSharp.Interpreter -{ - /// - /// This class contains extension methods providing async wrappers of many methods. - /// Asynchronous execution is performed by scheduling the method on the thread pool (through a Task.Factory.StartNew). - /// - /// This type is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - public static class AsyncExtensions - { - private static Task ExecAsync(Func func) - { - return Task.Factory.StartNew(func); - } - - private static Task ExecAsyncVoid(Action func) - { - return Task.Factory.StartNew(func); - } - - - - /// - /// Asynchronously calls this function with the specified args - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The function. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Closure function) - { - return ExecAsync(() => function.Call()); - } - - /// - /// Asynchronously calls this function with the specified args - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The function. - /// The arguments to pass to the function. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Closure function, params object[] args) - { - return ExecAsync(() => function.Call(args)); - } - - /// - /// Asynchronously calls this function with the specified args - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The function. - /// The arguments to pass to the function. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Closure function, params DynValue[] args) - { - return ExecAsync(() => function.Call(args)); - } - - /// - /// Asynchronously loads and executes a string containing a Lua/MoonSharp script. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The code. - /// The global context. - /// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file. - /// - /// A DynValue containing the result of the processing of the loaded chunk. - /// - public static Task DoStringAsync(this Script script, string code, Table globalContext = null, string codeFriendlyName = null) - { - return ExecAsync(() => script.DoString(code, globalContext, codeFriendlyName)); - } - - - /// - /// Asynchronously loads and executes a stream containing a Lua/MoonSharp script. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The stream. - /// The global context. - /// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file. - /// - /// A DynValue containing the result of the processing of the loaded chunk. - /// - public static Task DoStreamAsync(this Script script, Stream stream, Table globalContext = null, string codeFriendlyName = null) - { - return ExecAsync(() => script.DoStream(stream, globalContext, codeFriendlyName)); - } - - - /// - /// Asynchronously loads and executes a file containing a Lua/MoonSharp script. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The filename. - /// The global context. - /// Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file. - /// - /// A DynValue containing the result of the processing of the loaded chunk. - /// - public static Task DoFileAsync(this Script script, string filename, Table globalContext = null, string codeFriendlyName = null) - { - return ExecAsync(() => script.DoFile(filename, globalContext, codeFriendlyName)); - } - - /// - /// Asynchronously loads a string containing a Lua/MoonSharp function. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The code. - /// The global table to bind to this chunk. - /// Name of the function used to report errors, etc. - /// - /// A DynValue containing a function which will execute the loaded code. - /// - public static Task LoadFunctionAsync(this Script script, string code, Table globalTable = null, string funcFriendlyName = null) - { - return ExecAsync(() => script.LoadFunction(code, globalTable, funcFriendlyName)); - } - - - - /// - /// Asynchronously loads a string containing a Lua/MoonSharp script. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The code. - /// The global table to bind to this chunk. - /// Name of the code - used to report errors, etc. - /// - /// A DynValue containing a function which will execute the loaded code. - /// - public static Task LoadStringAsync(this Script script, string code, Table globalTable = null, string codeFriendlyName = null) - { - return ExecAsync(() => script.LoadString(code, globalTable, codeFriendlyName)); - } - - - - /// - /// Asynchronously loads a Lua/MoonSharp script from a System.IO.Stream. NOTE: This will *NOT* close the stream! - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The stream containing code. - /// The global table to bind to this chunk. - /// Name of the code - used to report errors, etc. - /// - /// A DynValue containing a function which will execute the loaded code. - /// - public static Task LoadStreamAsync(this Script script, Stream stream, Table globalTable = null, string codeFriendlyName = null) - { - return ExecAsync(() => script.LoadStream(stream, globalTable, codeFriendlyName)); - } - - - /// - /// Asynchronously dumps a function on the specified stream. - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The function. - /// The stream. - /// - /// function arg is not a function! - /// or - /// stream is readonly! - /// or - /// function arg has upvalues other than _ENV - public static Task DumpAsync(this Script script, DynValue function, Stream stream) - { - return ExecAsyncVoid(() => script.Dump(function, stream)); - } - - - - /// - /// Asynchronously loads a string containing a Lua/MoonSharp script. - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The code. - /// The global table to bind to this chunk. - /// The filename to be used in error messages. - /// - /// A DynValue containing a function which will execute the loaded code. - /// - public static Task LoadFileAsync(this Script script, string filename, Table globalContext = null, string friendlyFilename = null) - { - return ExecAsync(() => script.LoadFile(filename, globalContext, friendlyFilename)); - } - - - - /// - /// Calls the specified function. - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The Lua/MoonSharp function to be called - /// - /// The return value(s) of the function call. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Script script, DynValue function) - { - return ExecAsync(() => script.Call(function)); - } - - - /// - /// Asynchronously calls the specified function. - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The Lua/MoonSharp function to be called - /// The arguments to pass to the function. - /// - /// The return value(s) of the function call. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Script script, DynValue function, params DynValue[] args) - { - return ExecAsync(() => script.Call(function, args)); - } - - - - /// - /// Asynchronously calls the specified function. - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The Lua/MoonSharp function to be called - /// The arguments to pass to the function. - /// - /// The return value(s) of the function call. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Script script, DynValue function, params object[] args) - { - return ExecAsync(() => script.Call(function, args)); - } - - - - /// - /// Asynchronously calls the specified function. - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The Lua/MoonSharp function to be called - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Script script, object function) - { - return ExecAsync(() => script.Call(function)); - } - - - /// - /// Asynchronously calls the specified function. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The Lua/MoonSharp function to be called - /// The arguments to pass to the function. - /// - /// Thrown if function is not of DataType.Function - public static Task CallAsync(this Script script, object function, params object[] args) - { - return ExecAsync(() => script.Call(function, args)); - } - - /// - /// Asynchronously creates a new dynamic expression. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The script. - /// The code of the expression. - /// - public static Task CreateDynamicExpressionAsync(this Script script, string code) - { - return ExecAsync(() => script.CreateDynamicExpression(code)); - } - - /// - /// Asynchronously evaluates a REPL command. - /// This method returns the result of the computation, or null if more input is needed for having valid code. - /// In case of errors, exceptions are propagated to the caller. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The interpreter. - /// The input. - /// - /// This method returns the result of the computation, or null if more input is needed for a computation. - /// - public static Task EvaluateAsync(this ReplInterpreter interpreter, string input) - { - return ExecAsync(() => interpreter.Evaluate(input)); - } - - /// - /// Resumes the coroutine. - /// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The coroutine - /// The arguments. - /// - /// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead - public static Task ResumeAsync(this Coroutine cor, params DynValue[] args) - { - return ExecAsync(() => cor.Resume(args)); - } - - - /// - /// Resumes the coroutine. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The coroutine - /// The ScriptExecutionContext. - /// The arguments. - /// - public static Task ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params DynValue[] args) - { - return ExecAsync(() => cor.Resume(context, args)); - } - - /// - /// Resumes the coroutine. - /// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The coroutine - /// - /// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead - public static Task ResumeAsync(this Coroutine cor) - { - return ExecAsync(() => cor.Resume()); - } - - - /// - /// Resumes the coroutine. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The coroutine - /// The ScriptExecutionContext. - /// - public static Task ResumeAsync(this Coroutine cor, ScriptExecutionContext context) - { - return ExecAsync(() => cor.Resume(context)); - } - - /// - /// Resumes the coroutine. - /// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead. - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The coroutine - /// The arguments. - /// - /// Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead. - public static Task ResumeAsync(this Coroutine cor, params object[] args) - { - return ExecAsync(() => cor.Resume(args)); - } - - - /// - /// Resumes the coroutine - /// - /// This method is supported only on .NET 4.x and .NET 4.x PCL targets. - /// - /// The coroutine - /// The ScriptExecutionContext. - /// The arguments. - /// - public static Task ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params object[] args) - { - return ExecAsync(() => cor.Resume(context, args)); - } - } -} -#endif diff --git a/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs b/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs deleted file mode 100644 index cd51912c..00000000 --- a/src/MoonSharp.Interpreter/CoreLib/StringLib/KopiLua_StrLib.cs +++ /dev/null @@ -1,998 +0,0 @@ -// Disable warnings about XML documentation -#pragma warning disable 1591 - -// -// This part taken from KopiLua - https://github.com/NLua/KopiLua -// -// ========================================================================================================= -// -// Kopi Lua License -// ---------------- -// MIT License for KopiLua -// Copyright (c) 2012 LoDC -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or substantial -// portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// =============================================================================== -// Lua License -// ----------- -// Lua is licensed under the terms of the MIT license reproduced below. -// This means that Lua is free software and can be used for both academic -// and commercial purposes at absolutely no cost. -// For details and rationale, see http://www.lua.org/license.html . -// =============================================================================== -// Copyright (C) 1994-2008 Lua.org, PUC-Rio. -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - - -using MoonSharp.Interpreter.Interop.LuaStateInterop; -using lua_Integer = System.Int32; -using LUA_INTFRM_T = System.Int64; -using ptrdiff_t = System.Int32; -using UNSIGNED_LUA_INTFRM_T = System.UInt64; - -namespace MoonSharp.Interpreter.CoreLib.StringLib -{ - internal class KopiLua_StringLib : LuaBase - { - public const int LUA_MAXCAPTURES = 32; - - private static ptrdiff_t posrelat(ptrdiff_t pos, uint len) - { - /* relative string position: negative means back from end */ - if (pos < 0) pos += (ptrdiff_t)len + 1; - return (pos >= 0) ? pos : 0; - } - - /* - ** {====================================================== - ** PATTERN MATCHING - ** ======================================================= - */ - - - public const int CAP_UNFINISHED = (-1); - public const int CAP_POSITION = (-2); - - public class MatchState - { - - public MatchState() - { - for (int i = 0; i < LUA_MAXCAPTURES; i++) - capture[i] = new capture_(); - } - - public int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ - public CharPtr src_init; /* init of source string */ - public CharPtr src_end; /* end (`\0') of source string */ - public LuaState L; - public int level; /* total number of captures (finished or unfinished) */ - - public class capture_ - { - public CharPtr init; - public ptrdiff_t len; - }; - public capture_[] capture = new capture_[LUA_MAXCAPTURES]; - }; - - - public const int MAXCCALLS = 1000; - public const char L_ESC = '%'; - public const string SPECIALS = "^$*+?.([%-"; - - - private static int check_capture(MatchState ms, int l) - { - l -= '1'; - if (l < 0 || l >= ms.level || ms.capture[l].len == CAP_UNFINISHED) - return LuaLError(ms.L, "invalid capture index {0}", l + 1); - return l; - } - - - - private static int capture_to_close(MatchState ms) - { - int level = ms.level; - for (level--; level >= 0; level--) - if (ms.capture[level].len == CAP_UNFINISHED) return level; - return LuaLError(ms.L, "invalid pattern capture"); - } - - - private static CharPtr classend(MatchState ms, CharPtr p) - { - p = new CharPtr(p); - char c = p[0]; - p = p.next(); - switch (c) - { - case L_ESC: - { - if (p[0] == '\0') - LuaLError(ms.L, "malformed pattern (ends with " + LUA_QL("%") + ")"); - return p + 1; - } - case '[': - { - if (p[0] == '^') p = p.next(); - do - { /* look for a `]' */ - if (p[0] == '\0') - LuaLError(ms.L, "malformed pattern (missing " + LUA_QL("]") + ")"); - c = p[0]; - p = p.next(); - if (c == L_ESC && p[0] != '\0') - p = p.next(); /* skip escapes (e.g. `%]') */ - } while (p[0] != ']'); - return p + 1; - } - default: - { - return p; - } - } - } - - - - private static int match_class(char c, char cl) - { - bool res; - switch (tolower(cl)) - { - case 'a': res = isalpha(c); break; - case 'c': res = iscntrl(c); break; - case 'd': res = isdigit(c); break; - case 'l': res = islower(c); break; - case 'p': res = ispunct(c); break; - case 's': res = isspace(c); break; - case 'g': res = isgraph(c); break; - case 'u': res = isupper(c); break; - case 'w': res = isalnum(c); break; - case 'x': res = isxdigit((char)c); break; - case 'z': res = (c == 0); break; - default: return (cl == c) ? 1 : 0; - } - return (islower(cl) ? (res ? 1 : 0) : ((!res) ? 1 : 0)); - } - - - - private static int matchbracketclass(int c, CharPtr p, CharPtr ec) - { - int sig = 1; - if (p[1] == '^') - { - sig = 0; - p = p.next(); /* skip the `^' */ - } - while ((p = p.next()) < ec) - { - if (p == L_ESC) - { - p = p.next(); - if (match_class((char)c, (char)(p[0])) != 0) - return sig; - } - else if ((p[1] == '-') && (p + 2 < ec)) - { - p += 2; - if ((byte)((p[-2])) <= c && (c <= (byte)p[0])) - return sig; - } - else if ((byte)(p[0]) == c) return sig; - } - return (sig == 0) ? 1 : 0; - } - - - private static int singlematch(int c, CharPtr p, CharPtr ep) - { - switch (p[0]) - { - case '.': return 1; /* matches any char */ - case L_ESC: return match_class((char)c, (char)(p[1])); - case '[': return matchbracketclass(c, p, ep - 1); - default: return ((byte)(p[0]) == c) ? 1 : 0; - } - } - - - private static CharPtr matchbalance(MatchState ms, CharPtr s, - CharPtr p) - { - if ((p[0] == 0) || (p[1] == 0)) - LuaLError(ms.L, "unbalanced pattern"); - if (s[0] != p[0]) return null; - else - { - int b = p[0]; - int e = p[1]; - int cont = 1; - while ((s = s.next()) < ms.src_end) - { - if (s[0] == e) - { - if (--cont == 0) return s + 1; - } - else if (s[0] == b) cont++; - } - } - return null; /* string ends out of balance */ - } - - - private static CharPtr max_expand(MatchState ms, CharPtr s, - CharPtr p, CharPtr ep) - { - ptrdiff_t i = 0; /* counts maximum expand for item */ - while ((s + i < ms.src_end) && (singlematch((byte)(s[i]), p, ep) != 0)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i >= 0) - { - CharPtr res = match(ms, (s + i), ep + 1); - if (res != null) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return null; - } - - - private static CharPtr min_expand(MatchState ms, CharPtr s, - CharPtr p, CharPtr ep) - { - for (; ; ) - { - CharPtr res = match(ms, s, ep + 1); - if (res != null) - return res; - else if ((s < ms.src_end) && (singlematch((byte)(s[0]), p, ep) != 0)) - s = s.next(); /* try with one more repetition */ - else return null; - } - } - - - private static CharPtr start_capture(MatchState ms, CharPtr s, - CharPtr p, int what) - { - CharPtr res; - int level = ms.level; - if (level >= LUA_MAXCAPTURES) LuaLError(ms.L, "too many captures"); - ms.capture[level].init = s; - ms.capture[level].len = what; - ms.level = level + 1; - if ((res = match(ms, s, p)) == null) /* match failed? */ - ms.level--; /* undo capture */ - return res; - } - - - private static CharPtr end_capture(MatchState ms, CharPtr s, - CharPtr p) - { - int l = capture_to_close(ms); - CharPtr res; - ms.capture[l].len = s - ms.capture[l].init; /* close capture */ - if ((res = match(ms, s, p)) == null) /* match failed? */ - ms.capture[l].len = CAP_UNFINISHED; /* undo capture */ - return res; - } - - - private static CharPtr match_capture(MatchState ms, CharPtr s, int l) - { - uint len; - l = check_capture(ms, l); - len = (uint)ms.capture[l].len; - if ((uint)(ms.src_end - s) >= len && - memcmp(ms.capture[l].init, s, len) == 0) - return s + len; - else return null; - } - - - - private static CharPtr match(MatchState ms, CharPtr s, CharPtr p) - { - s = new CharPtr(s); - p = new CharPtr(p); - if (ms.matchdepth-- == 0) - LuaLError(ms.L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ - switch (p[0]) - { - case '(': - { /* start capture */ - if (p[1] == ')') /* position capture? */ - return start_capture(ms, s, p + 2, CAP_POSITION); - else - return start_capture(ms, s, p + 1, CAP_UNFINISHED); - } - case ')': - { /* end capture */ - return end_capture(ms, s, p + 1); - } - case L_ESC: - { - switch (p[1]) - { - case 'b': - { /* balanced string? */ - s = matchbalance(ms, s, p + 2); - if (s == null) return null; - p += 4; goto init; /* else return match(ms, s, p+4); */ - } - case 'f': - { /* frontier? */ - CharPtr ep; char previous; - p += 2; - if (p[0] != '[') - LuaLError(ms.L, "missing " + LUA_QL("[") + " after " + - LUA_QL("%f") + " in pattern"); - ep = classend(ms, p); /* points to what is next */ - previous = (s == ms.src_init) ? '\0' : s[-1]; - if ((matchbracketclass((byte)(previous), p, ep - 1) != 0) || - (matchbracketclass((byte)(s[0]), p, ep - 1) == 0)) return null; - p = ep; goto init; /* else return match(ms, s, ep); */ - } - default: - { - if (isdigit((char)(p[1]))) - { /* capture results (%0-%9)? */ - s = match_capture(ms, s, (byte)(p[1])); - if (s == null) return null; - p += 2; goto init; /* else return match(ms, s, p+2) */ - } - //ismeretlen hiba miatt lett ide átmásolva - { /* it is a pattern item */ - CharPtr ep = classend(ms, p); /* points to what is next */ - int m = (s < ms.src_end) && (singlematch((byte)(s[0]), p, ep) != 0) ? 1 : 0; - switch (ep[0]) - { - case '?': - { /* optional */ - CharPtr res; - if ((m != 0) && ((res = match(ms, s + 1, ep + 1)) != null)) - return res; - p = ep + 1; goto init; /* else return match(ms, s, ep+1); */ - } - case '*': - { /* 0 or more repetitions */ - return max_expand(ms, s, p, ep); - } - case '+': - { /* 1 or more repetitions */ - return ((m != 0) ? max_expand(ms, s + 1, p, ep) : null); - } - case '-': - { /* 0 or more repetitions (minimum) */ - return min_expand(ms, s, p, ep); - } - default: - { - if (m == 0) return null; - s = s.next(); p = ep; goto init; /* else return match(ms, s+1, ep); */ - } - } - } - //goto dflt; /* case default */ - } - } - } - case '\0': - { /* end of pattern */ - return s; /* match succeeded */ - } - case '$': - { - if (p[1] == '\0') /* is the `$' the last char in pattern? */ - return (s == ms.src_end) ? s : null; /* check end of string */ - else goto dflt; - } - default: - dflt: - { /* it is a pattern item */ - CharPtr ep = classend(ms, p); /* points to what is next */ - int m = (s < ms.src_end) && (singlematch((byte)(s[0]), p, ep) != 0) ? 1 : 0; - switch (ep[0]) - { - case '?': - { /* optional */ - CharPtr res; - if ((m != 0) && ((res = match(ms, s + 1, ep + 1)) != null)) - return res; - p = ep + 1; goto init; /* else return match(ms, s, ep+1); */ - } - case '*': - { /* 0 or more repetitions */ - return max_expand(ms, s, p, ep); - } - case '+': - { /* 1 or more repetitions */ - return ((m != 0) ? max_expand(ms, s + 1, p, ep) : null); - } - case '-': - { /* 0 or more repetitions (minimum) */ - return min_expand(ms, s, p, ep); - } - default: - { - if (m == 0) return null; - s = s.next(); p = ep; goto init; /* else return match(ms, s+1, ep); */ - } - } - } - } - } - - - - private static CharPtr lmemfind(CharPtr s1, uint l1, - CharPtr s2, uint l2) - { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return null; /* avoids a negative `l1' */ - else - { - CharPtr init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1 - l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = memchr(s1, s2[0], l1)) != null) - { - init = init.next(); /* 1st char is already checked */ - if (memcmp(init, s2 + 1, l2) == 0) - return init - 1; - else - { /* correct `l1' and `s1' to try again */ - l1 -= (uint)(init - s1); - s1 = init; - } - } - return null; /* not found */ - } - } - - - private static void push_onecapture(MatchState ms, int i, CharPtr s, - CharPtr e) - { - if (i >= ms.level) - { - if (i == 0) /* ms.level == 0, too */ - LuaPushLString(ms.L, s, (uint)(e - s)); /* add whole match */ - else - LuaLError(ms.L, "invalid capture index"); - } - else - { - ptrdiff_t l = ms.capture[i].len; - if (l == CAP_UNFINISHED) LuaLError(ms.L, "unfinished capture"); - if (l == CAP_POSITION) - LuaPushInteger(ms.L, ms.capture[i].init - ms.src_init + 1); - else - LuaPushLString(ms.L, ms.capture[i].init, (uint)l); - } - } - - - private static int push_captures(MatchState ms, CharPtr s, CharPtr e) - { - int i; - int nlevels = ((ms.level == 0) && (s != null)) ? 1 : ms.level; - LuaLCheckStack(ms.L, nlevels, "too many captures"); - for (i = 0; i < nlevels; i++) - push_onecapture(ms, i, s, e); - return nlevels; /* number of strings pushed */ - } - - - private static int str_find_aux(LuaState L, int find) - { - uint l1, l2; - CharPtr s = LuaLCheckLString(L, 1, out l1); - CharPtr p = PatchPattern(LuaLCheckLString(L, 2, out l2)); - - ptrdiff_t init = posrelat(LuaLOptInteger(L, 3, 1), l1) - 1; - if (init < 0) init = 0; - else if ((uint)(init) > l1) init = (ptrdiff_t)l1; - if ((find != 0) && ((LuaToBoolean(L, 4) != 0) || /* explicit request? */ - strpbrk(p, SPECIALS) == null)) - { /* or no special characters? */ - /* do a plain search */ - CharPtr s2 = lmemfind(s + init, (uint)(l1 - init), p, (uint)(l2)); - if (s2 != null) - { - LuaPushInteger(L, s2 - s + 1); - LuaPushInteger(L, (int)(s2 - s + l2)); - return 2; - } - } - else - { - MatchState ms = new MatchState(); - int anchor = 0; - if (p[0] == '^') - { - p = p.next(); - anchor = 1; - } - CharPtr s1 = s + init; - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s + l1; - do - { - CharPtr res; - ms.level = 0; - // LuaAssert(ms.matchdepth == MAXCCALLS); - ms.matchdepth = MAXCCALLS; - if ((res = match(ms, s1, p)) != null) - { - if (find != 0) - { - LuaPushInteger(L, s1 - s + 1); /* start */ - LuaPushInteger(L, res - s); /* end */ - return push_captures(ms, null, null) + 2; - } - else - return push_captures(ms, s1, res); - } - } while (((s1 = s1.next()) <= ms.src_end) && (anchor == 0)); - } - LuaPushNil(L); /* not found */ - return 1; - } - - - public static int str_find(LuaState L) - { - return str_find_aux(L, 1); - } - - - public static int str_match(LuaState L) - { - return str_find_aux(L, 0); - } - - private class GMatchAuxData - { - public CharPtr S; - public CharPtr P; - public uint LS; - public uint POS; - } - - - private static int gmatch_aux(LuaState L, GMatchAuxData auxdata) - { - MatchState ms = new MatchState(); - uint ls = auxdata.LS; - CharPtr s = auxdata.S; - CharPtr p = auxdata.P; - CharPtr src; - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = s; - ms.src_end = s + ls; - for (src = s + auxdata.POS; - src <= ms.src_end; - src = src.next()) - { - CharPtr e; - ms.level = 0; - //LuaAssert(ms.matchdepth == MAXCCALLS); - ms.matchdepth = MAXCCALLS; - - if ((e = match(ms, src, p)) != null) - { - lua_Integer newstart = e - s; - if (e == src) newstart++; /* empty match? go at least one position */ - auxdata.POS = (uint)newstart; - return push_captures(ms, src, e); - } - } - return 0; /* not found */ - } - - - private static DynValue gmatch_aux_2(ScriptExecutionContext executionContext, CallbackArguments args) - { - return executionContext.EmulateClassicCall(args, "gmatch", - L => gmatch_aux(L, (GMatchAuxData)executionContext.AdditionalData)); - } - - - public static int str_gmatch(LuaState L) - { - CallbackFunction C = new CallbackFunction(gmatch_aux_2, "gmatch"); - string s = ArgAsType(L, 1, DataType.String, false).String; - string p = PatchPattern(ArgAsType(L, 2, DataType.String, false).String); - - - C.AdditionalData = new GMatchAuxData() - { - S = new CharPtr(s), - P = new CharPtr(p), - LS = (uint)s.Length, - POS = 0 - }; - - L.Push(DynValue.NewCallback(C)); - - return 1; - } - - - private static int gfind_nodef(LuaState L) - { - return LuaLError(L, LUA_QL("string.gfind") + " was renamed to " + - LUA_QL("string.gmatch")); - } - - - private static void add_s(MatchState ms, LuaLBuffer b, CharPtr s, CharPtr e) - { - uint l, i; - CharPtr news = LuaToLString(ms.L, 3, out l); - for (i = 0; i < l; i++) - { - if (news[i] != L_ESC) - LuaLAddChar(b, news[i]); - else - { - i++; /* skip ESC */ - if (!isdigit((char)(news[i]))) - { - if (news[i] != L_ESC) - { - LuaLError(ms.L, "invalid use of '%' in replacement string"); - } - LuaLAddChar(b, news[i]); - } - else if (news[i] == '0') - LuaLAddLString(b, s, (uint)(e - s)); - else - { - push_onecapture(ms, news[i] - '1', s, e); - LuaLAddValue(b); /* add capture to accumulated result */ - } - } - } - } - - - - - private static void add_value(MatchState ms, LuaLBuffer b, CharPtr s, - CharPtr e) - { - LuaState L = ms.L; - switch (LuaType(L, 3)) - { - case LUA_TNUMBER: - case LUA_TSTRING: - { - add_s(ms, b, s, e); - return; - } - // case LUA_TUSERDATA: /// +++ does this make sense ?? - case LUA_TFUNCTION: - { - int n; - LuaPushValue(L, 3); - n = push_captures(ms, s, e); - LuaCall(L, n, 1); - break; - } - case LUA_TTABLE: - { - push_onecapture(ms, 0, s, e); - LuaGetTable(L, 3); - break; - } - } - if (LuaToBoolean(L, -1) == 0) - { /* nil or false? */ - LuaPop(L, 1); - LuaPushLString(L, s, (uint)(e - s)); /* keep original text */ - } - else if (LuaIsString(L, -1) == 0) - LuaLError(L, "invalid replacement value (a {0})", LuaLTypeName(L, -1)); - - LuaLAddValue(b); /* add result to accumulator */ - } - - - public static int str_gsub(LuaState L) - { - uint srcl; - CharPtr src = LuaLCheckLString(L, 1, out srcl); - CharPtr p = PatchPattern(LuaLCheckStringStr(L, 2)); - int tr = LuaType(L, 3); - int max_s = LuaLOptInt(L, 4, (int)(srcl + 1)); - int anchor = 0; - if (p[0] == '^') - { - p = p.next(); - anchor = 1; - } - int n = 0; - MatchState ms = new MatchState(); - LuaLBuffer b = new LuaLBuffer(L); - LuaLArgCheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || - tr == LUA_TFUNCTION || tr == LUA_TTABLE || - tr == LUA_TUSERDATA, 3, - "string/function/table expected"); - LuaLBuffInit(L, b); - ms.L = L; - ms.matchdepth = MAXCCALLS; - ms.src_init = src; - ms.src_end = src + srcl; - while (n < max_s) - { - CharPtr e; - ms.level = 0; - //LuaAssert(ms.matchdepth == MAXCCALLS); - ms.matchdepth = MAXCCALLS; - e = match(ms, src, p); - if (e != null) - { - n++; - add_value(ms, b, src, e); - } - if ((e != null) && e > src) /* non empty match? */ - src = e; /* skip it */ - else if (src < ms.src_end) - { - char c = src[0]; - src = src.next(); - LuaLAddChar(b, c); - } - else break; - if (anchor != 0) break; - } - LuaLAddLString(b, src, (uint)(ms.src_end - src)); - LuaLPushResult(b); - LuaPushInteger(L, n); /* number of substitutions */ - return 2; - } - - - /* }====================================================== */ - - - /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ - public const int MAX_ITEM = 512; - /* valid flags in a format specification */ - public const string FLAGS = "-+ #0"; - /* - ** maximum size of each format specification (such as '%-099.99d') - ** (+10 accounts for %99.99x plus margin of error) - */ - public static readonly int MAX_FORMAT = (FLAGS.Length + 1) + (LUA_INTFRMLEN.Length + 1) + 10; - - - private static void addquoted(LuaState L, LuaLBuffer b, int arg) - { - uint l; - CharPtr s = LuaLCheckLString(L, arg, out l); - LuaLAddChar(b, '"'); - while ((l--) != 0) - { - switch (s[0]) - { - case '"': - case '\\': - case '\n': - { - LuaLAddChar(b, '\\'); - LuaLAddChar(b, s[0]); - break; - } - case '\r': - { - LuaLAddLString(b, "\\r", 2); - break; - } - default: - { - if (s[0] < (char)16) - { - bool isfollowedbynum = false; - - if (l >= 1) - { - if (char.IsNumber(s[1])) - isfollowedbynum = true; - } - - if (isfollowedbynum) - LuaLAddString(b, string.Format("\\{0:000}", (int)s[0])); - else - LuaLAddString(b, string.Format("\\{0}", (int)s[0])); - } - else - { - LuaLAddChar(b, s[0]); - } - break; - } - } - s = s.next(); - } - LuaLAddChar(b, '"'); - } - - private static CharPtr scanformat(LuaState L, CharPtr strfrmt, CharPtr form) - { - CharPtr p = strfrmt; - while (p[0] != '\0' && strchr(FLAGS, p[0]) != null) p = p.next(); /* skip flags */ - if ((uint)(p - strfrmt) >= (FLAGS.Length + 1)) - LuaLError(L, "invalid format (repeated flags)"); - if (isdigit((byte)(p[0]))) p = p.next(); /* skip width */ - if (isdigit((byte)(p[0]))) p = p.next(); /* (2 digits at most) */ - if (p[0] == '.') - { - p = p.next(); - if (isdigit((byte)(p[0]))) p = p.next(); /* skip precision */ - if (isdigit((byte)(p[0]))) p = p.next(); /* (2 digits at most) */ - } - if (isdigit((byte)(p[0]))) - LuaLError(L, "invalid format (width or precision too long)"); - form[0] = '%'; - form = form.next(); - strncpy(form, strfrmt, p - strfrmt + 1); - form += p - strfrmt + 1; - form[0] = '\0'; - return p; - } - - - private static void addintlen(CharPtr form) - { - uint l = (uint)strlen(form); - char spec = form[l - 1]; - strcpy(form + l - 1, LUA_INTFRMLEN); - form[l + (LUA_INTFRMLEN.Length + 1) - 2] = spec; - form[l + (LUA_INTFRMLEN.Length + 1) - 1] = '\0'; - } - - - public static int str_format(LuaState L) - { - int top = LuaGetTop(L); - int arg = 1; - uint sfl; - CharPtr strfrmt = LuaLCheckLString(L, arg, out sfl); - CharPtr strfrmt_end = strfrmt + sfl; - LuaLBuffer b = new LuaLBuffer(L); - LuaLBuffInit(L, b); - while (strfrmt < strfrmt_end) - { - if (strfrmt[0] != L_ESC) - { - LuaLAddChar(b, strfrmt[0]); - strfrmt = strfrmt.next(); - } - else if (strfrmt[1] == L_ESC) - { - LuaLAddChar(b, strfrmt[0]); /* %% */ - strfrmt = strfrmt + 2; - } - else - { /* format item */ - strfrmt = strfrmt.next(); - CharPtr form = new char[MAX_FORMAT]; /* to store the format (`%...') */ - CharPtr buff = new char[MAX_ITEM]; /* to store the formatted item */ - if (++arg > top) - LuaLArgError(L, arg, "no value"); - strfrmt = scanformat(L, strfrmt, form); - char ch = strfrmt[0]; - strfrmt = strfrmt.next(); - switch (ch) - { - case 'c': - { - sprintf(buff, form, (int)LuaLCheckNumber(L, arg)); - break; - } - case 'd': - case 'i': - { - addintlen(form); - sprintf(buff, form, (LUA_INTFRM_T)LuaLCheckNumber(L, arg)); - break; - } - case 'o': - case 'u': - case 'x': - case 'X': - { - addintlen(form); - sprintf(buff, form, (UNSIGNED_LUA_INTFRM_T)LuaLCheckNumber(L, arg)); - break; - } - case 'e': - case 'E': - case 'f': - case 'g': - case 'G': - { - sprintf(buff, form, (double)LuaLCheckNumber(L, arg)); - break; - } - case 'q': - { - addquoted(L, b, arg); - continue; /* skip the 'addsize' at the end */ - } - case 's': - { - uint l; - CharPtr s = LuaLCheckLString(L, arg, out l, true); - if ((strchr(form, '.') == null) && l >= 100) - { - /* no precision and string is too long to be formatted; - keep original string */ - LuaPushValue(L, arg); - LuaLAddValue(b); - continue; /* skip the `addsize' at the end */ - } - else - { - sprintf(buff, form, s); - break; - } - } - default: - { /* also treat cases `pnLlh' */ - return LuaLError(L, "invalid option " + LUA_QL("%" + ch) + " to " + - LUA_QL("format"), strfrmt[-1]); - } - } - LuaLAddLString(b, buff, (uint)strlen(buff)); - } - } - LuaLPushResult(b); - return 1; - } - - - private static string PatchPattern(string charPtr) - { - return charPtr.Replace("\0", "%z"); - } - - - } -} diff --git a/src/MoonSharp.Interpreter/CoreLib/StringModule.cs b/src/MoonSharp.Interpreter/CoreLib/StringModule.cs deleted file mode 100644 index bdfc8e49..00000000 --- a/src/MoonSharp.Interpreter/CoreLib/StringModule.cs +++ /dev/null @@ -1,298 +0,0 @@ -// Disable warnings about XML documentation -#pragma warning disable 1591 - -using System; -using System.IO; -using System.Text; -using MoonSharp.Interpreter.CoreLib.StringLib; - -namespace MoonSharp.Interpreter.CoreLib -{ - /// - /// Class implementing string Lua functions - /// - [MoonSharpModule(Namespace = "string")] - public class StringModule - { - public const string BASE64_DUMP_HEADER = "MoonSharp_dump_b64::"; - - public static void MoonSharpInit(Table globalTable, Table stringTable) - { - Table stringMetatable = new Table(globalTable.OwnerScript); - stringMetatable.Set("__index", DynValue.NewTable(stringTable)); - globalTable.OwnerScript.SetTypeMetatable(DataType.String, stringMetatable); - } - - - [MoonSharpModuleMethod] - public static DynValue dump(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue fn = args.AsType(0, "dump", DataType.Function, false); - - try - { - byte[] bytes; - using (MemoryStream ms = new MemoryStream()) - { - executionContext.GetScript().Dump(fn, ms); - ms.Seek(0, SeekOrigin.Begin); - bytes = ms.ToArray(); - } - string base64 = Convert.ToBase64String(bytes); - return DynValue.NewString(BASE64_DUMP_HEADER + base64); - } - catch (Exception ex) - { - throw new ScriptRuntimeException(ex.Message); - } - } - - - [MoonSharpModuleMethod] - public static DynValue @char(ScriptExecutionContext executionContext, CallbackArguments args) - { - StringBuilder sb = new StringBuilder(args.Count); - - for (int i = 0; i < args.Count; i++) - { - DynValue v = args[i]; - double d = 0d; - - if (v.Type == DataType.String) - { - double? nd = v.CastToNumber(); - if (nd == null) - args.AsType(i, "char", DataType.Number, false); - else - d = nd.Value; - } - else - { - args.AsType(i, "char", DataType.Number, false); - d = v.Number; - } - - sb.Append((char)(d)); - } - - return DynValue.NewString(sb.ToString()); - } - - - [MoonSharpModuleMethod] - public static DynValue @byte(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue vs = args.AsType(0, "byte", DataType.String, false); - DynValue vi = args.AsType(1, "byte", DataType.Number, true); - DynValue vj = args.AsType(2, "byte", DataType.Number, true); - - return PerformByteLike(vs, vi, vj, - i => Unicode2Ascii(i)); - } - - [MoonSharpModuleMethod] - public static DynValue unicode(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue vs = args.AsType(0, "unicode", DataType.String, false); - DynValue vi = args.AsType(1, "unicode", DataType.Number, true); - DynValue vj = args.AsType(2, "unicode", DataType.Number, true); - - return PerformByteLike(vs, vi, vj, i => i); - } - - private static int Unicode2Ascii(int i) - { - if (i >= 0 && i < 255) - return i; - - return (int)'?'; - } - - private static DynValue PerformByteLike(DynValue vs, DynValue vi, DynValue vj, Func filter) - { - StringRange range = StringRange.FromLuaRange(vi, vj, null); - string s = range.ApplyToString(vs.String); - - int length = s.Length; - DynValue[] rets = new DynValue[length]; - - for (int i = 0; i < length; ++i) - { - rets[i] = DynValue.NewNumber(filter((int)s[i])); - } - - return DynValue.NewTuple(rets); - } - - - private static int? AdjustIndex(string s, DynValue vi, int defval) - { - if (vi.IsNil()) - return defval; - - int i = (int)Math.Round(vi.Number, 0); - - if (i == 0) - return null; - - if (i > 0) - return i - 1; - - return s.Length - i; - } - - [MoonSharpModuleMethod] - public static DynValue len(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue vs = args.AsType(0, "len", DataType.String, false); - return DynValue.NewNumber(vs.String.Length); - } - - - - [MoonSharpModuleMethod] - public static DynValue match(ScriptExecutionContext executionContext, CallbackArguments args) - { - return executionContext.EmulateClassicCall(args, "match", KopiLua_StringLib.str_match); - } - - - [MoonSharpModuleMethod] - public static DynValue gmatch(ScriptExecutionContext executionContext, CallbackArguments args) - { - return executionContext.EmulateClassicCall(args, "gmatch", KopiLua_StringLib.str_gmatch); - } - - [MoonSharpModuleMethod] - public static DynValue gsub(ScriptExecutionContext executionContext, CallbackArguments args) - { - return executionContext.EmulateClassicCall(args, "gsub", KopiLua_StringLib.str_gsub); - } - - [MoonSharpModuleMethod] - public static DynValue find(ScriptExecutionContext executionContext, CallbackArguments args) - { - return executionContext.EmulateClassicCall(args, "find", - KopiLua_StringLib.str_find); - } - - - [MoonSharpModuleMethod] - public static DynValue lower(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s = args.AsType(0, "lower", DataType.String, false); - return DynValue.NewString(arg_s.String.ToLower()); - } - - [MoonSharpModuleMethod] - public static DynValue upper(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s = args.AsType(0, "upper", DataType.String, false); - return DynValue.NewString(arg_s.String.ToUpper()); - } - - [MoonSharpModuleMethod] - public static DynValue rep(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s = args.AsType(0, "rep", DataType.String, false); - DynValue arg_n = args.AsType(1, "rep", DataType.Number, false); - DynValue arg_sep = args.AsType(2, "rep", DataType.String, true); - - if (String.IsNullOrEmpty(arg_s.String) || (arg_n.Number < 1)) - { - return DynValue.NewString(""); - } - - string sep = (arg_sep.IsNotNil()) ? arg_sep.String : null; - - int count = (int)arg_n.Number; - StringBuilder result = new StringBuilder(arg_s.String.Length * count); - - for (int i = 0; i < count; ++i) - { - if (i != 0 && sep != null) - result.Append(sep); - - result.Append(arg_s.String); - } - - return DynValue.NewString(result.ToString()); - } - - [MoonSharpModuleMethod] - public static DynValue format(ScriptExecutionContext executionContext, CallbackArguments args) - { - return executionContext.EmulateClassicCall(args, "format", KopiLua_StringLib.str_format); - } - - - - [MoonSharpModuleMethod] - public static DynValue reverse(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s = args.AsType(0, "reverse", DataType.String, false); - - if (String.IsNullOrEmpty(arg_s.String)) - { - return DynValue.NewString(""); - } - - char[] elements = arg_s.String.ToCharArray(); - Array.Reverse(elements); - - return DynValue.NewString(new String(elements)); - } - - [MoonSharpModuleMethod] - public static DynValue sub(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s = args.AsType(0, "sub", DataType.String, false); - DynValue arg_i = args.AsType(1, "sub", DataType.Number, true); - DynValue arg_j = args.AsType(2, "sub", DataType.Number, true); - - StringRange range = StringRange.FromLuaRange(arg_i, arg_j, -1); - string s = range.ApplyToString(arg_s.String); - - return DynValue.NewString(s); - } - - [MoonSharpModuleMethod] - public static DynValue startsWith(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s1 = args.AsType(0, "startsWith", DataType.String, true); - DynValue arg_s2 = args.AsType(1, "startsWith", DataType.String, true); - - if (arg_s1.IsNil() || arg_s2.IsNil()) - return DynValue.False; - - return DynValue.NewBoolean(arg_s1.String.StartsWith(arg_s2.String)); - } - - [MoonSharpModuleMethod] - public static DynValue endsWith(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s1 = args.AsType(0, "endsWith", DataType.String, true); - DynValue arg_s2 = args.AsType(1, "endsWith", DataType.String, true); - - if (arg_s1.IsNil() || arg_s2.IsNil()) - return DynValue.False; - - return DynValue.NewBoolean(arg_s1.String.EndsWith(arg_s2.String)); - } - - [MoonSharpModuleMethod] - public static DynValue contains(ScriptExecutionContext executionContext, CallbackArguments args) - { - DynValue arg_s1 = args.AsType(0, "contains", DataType.String, true); - DynValue arg_s2 = args.AsType(1, "contains", DataType.String, true); - - if (arg_s1.IsNil() || arg_s2.IsNil()) - return DynValue.False; - - return DynValue.NewBoolean(arg_s1.String.Contains(arg_s2.String)); - } - - } - - -} diff --git a/src/MoonSharp.Interpreter/DataStructs/LinkedListArrayIndex.cs b/src/MoonSharp.Interpreter/DataStructs/LinkedListArrayIndex.cs deleted file mode 100644 index 2d2ee362..00000000 --- a/src/MoonSharp.Interpreter/DataStructs/LinkedListArrayIndex.cs +++ /dev/null @@ -1,127 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MoonSharp.Interpreter.DataStructs -{ - internal class LinkedListArrayIndex : LinkedListIndex - { - - /// - /// Initializes a new instance of the class. - /// - /// The linked list to be indexed. - public LinkedListArrayIndex(LinkedList linkedList) : base(linkedList) { } - - private LinkedListNode[] positive; - - /// - /// Finds the node indexed by the specified key, or null. - /// - /// The key. - public override LinkedListNode Find(int key) - { - if (key >= 0) - { - if (positive != null && key < positive.Length) - return positive[key]; - } - return base.Find(key); - } - - /// - /// Updates or creates a new node in the linked list, indexed by the specified key. - /// - /// The key. - /// The value. - /// The previous value of the element - public override TValue Set(int key, TValue value) - { - LinkedListNode node = Find(key); - - if (node == null) - { - Add(key, value); - return default(TValue); - } - else - { - TValue val = node.Value; - node.Value = value; - return val; - } - } - - /// - /// Creates a new node in the linked list, indexed by the specified key. - /// - /// The key. - /// The value. - public override void Add(int key, TValue value) - { - if (key >= 0) - { - if (positive == null || key >= positive.Length) - { - int pLen = positive?.Length ?? 0; - int newLen = Math.Max(pLen + 16, pLen * 2); - if (key > newLen) - base.Add(key,value); - else - { - if (positive == null) positive = new LinkedListNode[16]; - else Array.Resize(ref positive, newLen); - var node = m_LinkedList.AddLast(value); - positive[key] = node; - } - } - else - { - var node = m_LinkedList.AddLast(value); - positive[key] = node; - } - } - else - { - base.Add(key, value); - } - } - - /// - /// Removes the specified key from the index, and the node indexed by the key from the linked list. - /// - /// The key. - public override bool Remove(int key) - { - if (key >= 0 && positive != null && key < positive.Length) - { - if (positive[key] != null) - { - positive[key] = null; - return true; - } - } - return base.Remove(key); - } - - /// - /// Clears this instance (removes all elements) - /// - public override void Clear() - { - if(positive != null) Array.Clear(positive, 0, positive.Length); - base.Clear(); - } - - public override bool ContainsKey(int key) - { - if (key >= 0 && positive != null && key < positive.Length) - { - if (positive[key] != null) - { - return true; - } - } - return base.ContainsKey(key); - } - } -} \ No newline at end of file diff --git a/src/MoonSharp.Interpreter/DataStructs/LinkedListIndex.cs b/src/MoonSharp.Interpreter/DataStructs/LinkedListIndex.cs deleted file mode 100644 index 374d3cdf..00000000 --- a/src/MoonSharp.Interpreter/DataStructs/LinkedListIndex.cs +++ /dev/null @@ -1,120 +0,0 @@ -using System.Collections.Generic; - -namespace MoonSharp.Interpreter.DataStructs -{ - /// - /// An index to accelerate operations on a LinkedList using a single key of type - /// More than one LinkedListIndex can index the same linked list, but every node in the linked list must be indexed by one and only one - /// LinkedListIndex object. - /// - /// The type of the key. Must implement Equals and GetHashCode appropriately. - /// The type of the values contained in the linked list. - internal class LinkedListIndex - { - protected LinkedList m_LinkedList; - Dictionary> m_Map = null; - - /// - /// Initializes a new instance of the class. - /// - /// The linked list to be indexed. - public LinkedListIndex(LinkedList linkedList) - { - m_LinkedList = linkedList; - } - - /// - /// Finds the node indexed by the specified key, or null. - /// - /// The key. - public virtual LinkedListNode Find(TKey key) - { - LinkedListNode node; - - if (m_Map == null) - return null; - - if (m_Map.TryGetValue(key, out node)) - return node; - - return null; - } - - /// - /// Updates or creates a new node in the linked list, indexed by the specified key. - /// - /// The key. - /// The value. - /// The previous value of the element - public virtual TValue Set(TKey key, TValue value) - { - LinkedListNode node = Find(key); - - if (node == null) - { - Add(key, value); - return default(TValue); - } - else - { - TValue val = node.Value; - node.Value = value; - return val; - } - } - - /// - /// Creates a new node in the linked list, indexed by the specified key. - /// - /// The key. - /// The value. - public virtual void Add(TKey key, TValue value) - { - var node = m_LinkedList.AddLast(value); - - if (m_Map == null) - m_Map = new Dictionary>(); - - m_Map.Add(key, node); - } - - /// - /// Removes the specified key from the index, and the node indexed by the key from the linked list. - /// - /// The key. - public virtual bool Remove(TKey key) - { - LinkedListNode node = Find(key); - - if (node != null) - { - m_LinkedList.Remove(node); - return m_Map.Remove(key); - } - - return false; - } - - - /// - /// Determines whether the index contains the specified key. - /// - /// The key. - public virtual bool ContainsKey(TKey key) - { - if (m_Map == null) - return false; - - return m_Map.ContainsKey(key); - } - - /// - /// Clears this instance (removes all elements) - /// - public virtual void Clear() - { - if(m_Map != null) - m_Map.Clear(); - } - } -} diff --git a/src/MoonSharp.Interpreter/Execution/Scopes/LoopTracker.cs b/src/MoonSharp.Interpreter/Execution/Scopes/LoopTracker.cs deleted file mode 100644 index 40297ea9..00000000 --- a/src/MoonSharp.Interpreter/Execution/Scopes/LoopTracker.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MoonSharp.Interpreter.DataStructs; -using MoonSharp.Interpreter.Execution.VM; - -namespace MoonSharp.Interpreter.Execution -{ - interface ILoop - { - void CompileBreak(ByteCode bc); - void CompileContinue(ByteCode bc); - bool IsBoundary(); - } - - - internal class LoopTracker - { - public FastStack Loops = new FastStack(32, 16384); - } -} diff --git a/src/MoonSharp.Interpreter/Execution/VM/ByteCode.cs b/src/MoonSharp.Interpreter/Execution/VM/ByteCode.cs deleted file mode 100755 index 1f332f0a..00000000 --- a/src/MoonSharp.Interpreter/Execution/VM/ByteCode.cs +++ /dev/null @@ -1,374 +0,0 @@ -#define EMIT_DEBUG_OPS - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using MoonSharp.Interpreter.Debugging; - -namespace MoonSharp.Interpreter.Execution.VM -{ - internal class ByteCode : RefIdObject - { - public List Code = new List(); - public List SourceRefs = new List(); - public Script Script { get; private set; } - private List m_SourceRefStack = new List(); - private SourceRef m_CurrentSourceRef = null; - - internal LoopTracker LoopTracker = new LoopTracker(); - - public Stack NilChainTargets = new Stack(); - - public ByteCode(Script script) - { - Script = script; - } - - - public IDisposable EnterSource(SourceRef sref) - { - return new SourceCodeStackGuard(sref, this); - } - - - private class SourceCodeStackGuard : IDisposable - { - ByteCode m_Bc; - - public SourceCodeStackGuard(SourceRef sref, ByteCode bc) - { - m_Bc = bc; - m_Bc.PushSourceRef(sref); - } - - public void Dispose() - { - m_Bc.PopSourceRef(); - } - } - - - public void PushSourceRef(SourceRef sref) - { - m_SourceRefStack.Add(sref); - m_CurrentSourceRef = sref; - } - - public void PopSourceRef() - { - m_SourceRefStack.RemoveAt(m_SourceRefStack.Count - 1); - m_CurrentSourceRef = (m_SourceRefStack.Count > 0) ? m_SourceRefStack[m_SourceRefStack.Count - 1] : null; - } - - public string Dump() - { - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < Code.Count; i++) - { - if (Code[i].OpCode == OpCode.Debug) - sb.AppendFormat(" {0}\n", Code[i]); - else - sb.AppendFormat("{0:X8} {1}\n", i, Code[i]); - } - - return sb.ToString(); - } - - public int GetJumpPointForNextInstruction() - { - return Code.Count; - } - public int GetJumpPointForLastInstruction() - { - return Code.Count - 1; - } - - private int AppendInstruction(Instruction c) - { - Code.Add(c); - SourceRefs.Add(m_CurrentSourceRef); - return Code.Count - 1; - } - - public void SetNumVal(int instruction, int val) - { - var ins = Code[instruction]; - ins.NumVal = val; - Code[instruction] = ins; - } - - public int Emit_Nop(string comment) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Nop, String = comment }); - } - - public int Emit_Invalid(string type) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Invalid, String = type }); - } - - public int Emit_Pop(int num = 1) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Pop, NumVal = num }); - } - - public void Emit_Call(int argCount, string debugName) - { - AppendInstruction(new Instruction() { OpCode = OpCode.Call, NumVal = argCount, String = debugName }); - } - - public void Emit_ThisCall(int argCount, string debugName) - { - AppendInstruction(new Instruction() { OpCode = OpCode.ThisCall, NumVal = argCount, String = debugName }); - } - - public int Emit_Literal(DynValue value) - { - switch (value.Type) - { - case DataType.Nil: - return AppendInstruction(new Instruction() {OpCode = OpCode.PushNil}); - case DataType.Boolean: - if (value.Boolean) - return AppendInstruction(new Instruction() {OpCode = OpCode.PushTrue}); - else - return AppendInstruction(new Instruction() {OpCode = OpCode.PushFalse}); - case DataType.Number: - return AppendInstruction(new Instruction() {OpCode = OpCode.PushNumber, Number = value.Number}); - case DataType.String: - return AppendInstruction(new Instruction() {OpCode = OpCode.PushString, String = value.String}); - } - throw new InvalidOperationException(value.Type.ToString()); - } - - public int Emit_StrFormat(int argCount) - { - return AppendInstruction(new Instruction() {OpCode = OpCode.StrFormat, NumVal = argCount}); - } - - public int Emit_Jump(OpCode jumpOpCode, int idx, int optPar = 0) - { - return AppendInstruction(new Instruction() { OpCode = jumpOpCode, NumVal = idx, NumVal2 = optPar }); - } - - public int Emit_MkTuple(int cnt) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.MkTuple, NumVal = cnt }); - } - - public int Emit_Operator(OpCode opcode) - { - var i = AppendInstruction(new Instruction() { OpCode = opcode }); - - if (opcode == OpCode.LessEq) - AppendInstruction(new Instruction() { OpCode = OpCode.CNot }); - - if (opcode == OpCode.Eq || opcode == OpCode.Less) - AppendInstruction(new Instruction() { OpCode = OpCode.ToBool }); - - return i; - } - - - [Conditional("EMIT_DEBUG_OPS")] - public void Emit_Debug(string str) - { - AppendInstruction(new Instruction() { OpCode = OpCode.Debug, String = str.Substring(0, Math.Min(32, str.Length)) }); - } - - public int Emit_Enter(RuntimeScopeBlock runtimeScopeBlock) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Clean, NumVal = runtimeScopeBlock.From, NumVal2 = runtimeScopeBlock.ToInclusive }); - } - - public int Emit_Leave(RuntimeScopeBlock runtimeScopeBlock) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Clean, NumVal = runtimeScopeBlock.From, NumVal2 = runtimeScopeBlock.To }); - } - - public int Emit_Exit(RuntimeScopeBlock runtimeScopeBlock) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Clean, NumVal = runtimeScopeBlock.From, NumVal2 = runtimeScopeBlock.ToInclusive }); - } - - public int Emit_Clean(RuntimeScopeBlock runtimeScopeBlock) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Clean, NumVal = runtimeScopeBlock.To + 1, NumVal2 = runtimeScopeBlock.ToInclusive }); - } - - public int Emit_CloseUp(SymbolRef sym) - { - if (sym.Type != SymbolRefType.Local) - throw new InternalErrorException("Can only emit CloseUp for locals"); - return AppendInstruction(new Instruction() { OpCode = OpCode.CloseUp, NumVal = sym.i_Index }); - } - - public int Emit_Closure(SymbolRef[] symbols, int jmpnum) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Closure, SymbolList = symbols, NumVal = jmpnum }); - } - - public int Emit_Args(params SymbolRef[] symbols) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Args, SymbolList = symbols }); - } - - public int Emit_Ret(int retvals) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Ret, NumVal = retvals }); - } - - public int Emit_Incr(int i) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Incr, NumVal = i }); - } - - public int Emit_NewTable(bool shared) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.NewTable, NumVal = shared ? 1 : 0 }); - } - - public int Emit_IterPrep() - { - return AppendInstruction(new Instruction() { OpCode = OpCode.IterPrep }); - } - - public int Emit_ExpTuple(int stackOffset) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.ExpTuple, NumVal = stackOffset }); - } - - public int Emit_IterUpd() - { - return AppendInstruction(new Instruction() { OpCode = OpCode.IterUpd }); - } - - public int Emit_Meta(string funcName, OpCodeMetadataType metaType) - { - return AppendInstruction(new Instruction() - { - OpCode = OpCode.Meta, - String = funcName, - NumVal2 = (int)metaType - }); - } - - public int Emit_Annot(Annotation[] annotations) - { - return AppendInstruction(new Instruction() - { - OpCode = OpCode.Annot, - Annotations = annotations - }); - } - - - public int Emit_BeginFn(RuntimeScopeFrame stackFrame) - { - return AppendInstruction(new Instruction() - { - OpCode = OpCode.BeginFn, - SymbolList = stackFrame.DebugSymbols.ToArray(), - NumVal = stackFrame.Count, - NumVal2 = stackFrame.ToFirstBlock, - }); - } - - public int Emit_Scalar() - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Scalar }); - } - - public int Emit_Load(SymbolRef sym) - { - switch (sym.Type) - { - case SymbolRefType.Global: - Emit_Load(sym.i_Env); - AppendInstruction(new Instruction() { OpCode = OpCode.Index, String = sym.i_Name }); - return 2; - case SymbolRefType.Local: - AppendInstruction(new Instruction() { OpCode = OpCode.Local, NumVal = sym.i_Index }); - return 1; - case SymbolRefType.Upvalue: - AppendInstruction(new Instruction() { OpCode = OpCode.Upvalue, NumVal = sym.i_Index }); - return 1; - default: - throw new InternalErrorException("Unexpected symbol type : {0}", sym); - } - } - - public int Emit_Store(SymbolRef sym, int stackofs, int tupleidx) - { - switch (sym.Type) - { - case SymbolRefType.Global: - Emit_Load(sym.i_Env); - AppendInstruction(new Instruction() { OpCode = OpCode.IndexSet, NumVal = stackofs, NumVal2 = tupleidx, String = sym.i_Name }); - return 2; - case SymbolRefType.Local: - AppendInstruction(new Instruction() { OpCode = OpCode.StoreLcl, Symbol = sym, NumVal = stackofs, NumVal2 = tupleidx }); - return 1; - case SymbolRefType.Upvalue: - AppendInstruction(new Instruction() { OpCode = OpCode.StoreUpv, Symbol = sym, NumVal = stackofs, NumVal2 = tupleidx }); - return 1; - default: - throw new InternalErrorException("Unexpected symbol type : {0}", sym); - } - } - - public int Emit_TblInitN() - { - return AppendInstruction(new Instruction() { OpCode = OpCode.TblInitN }); - } - - public int Emit_TblInitI(bool lastpos) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.TblInitI, NumVal = lastpos ? 1 : 0 }); - } - - public int Emit_Index(string index = null, bool isNameIndex = false, bool isExpList = false) - { - OpCode o; - if (isNameIndex) o = OpCode.IndexN; - else if (isExpList) o = OpCode.IndexL; - else o = OpCode.Index; - - return AppendInstruction(new Instruction() { OpCode = o, String = index }); - } - - public int Emit_IndexSet(int stackofs, int tupleidx, string index = null, bool isNameIndex = false, bool isExpList = false) - { - OpCode o; - if (isNameIndex) o = OpCode.IndexSetN; - else if (isExpList) o = OpCode.IndexSetL; - else o = OpCode.IndexSet; - - return AppendInstruction(new Instruction() { OpCode = o, NumVal = stackofs, NumVal2 = tupleidx, String = index }); - } - - public int Emit_Copy(int numval) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Copy, NumVal = numval }); - } - - public int Emit_CopyValue(int numval, int tupleidx) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Copy, NumVal = numval, NumVal2 = tupleidx }); - } - - public int Emit_Swap(int p1, int p2) - { - return AppendInstruction(new Instruction() { OpCode = OpCode.Swap, NumVal = p1, NumVal2 = p2 }); - } - - public int Emit_JLclInit(SymbolRef sym, int target) - { - if(sym.Type != SymbolRefType.Local) throw new InternalErrorException("Unexpected symbol type : {0}", sym); - return AppendInstruction(new Instruction() { OpCode = OpCode.JLclInit, NumVal = target, NumVal2 = sym.Index }); - } - } -} diff --git a/src/MoonSharp.Interpreter/Execution/VM/Instruction.cs b/src/MoonSharp.Interpreter/Execution/VM/Instruction.cs deleted file mode 100644 index 02f4f16d..00000000 --- a/src/MoonSharp.Interpreter/Execution/VM/Instruction.cs +++ /dev/null @@ -1,303 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using MoonSharp.Interpreter.Debugging; -using MoonSharp.Interpreter.IO; -using MoonSharp.Interpreter.Serialization; - -namespace MoonSharp.Interpreter.Execution.VM -{ - [StructLayout(LayoutKind.Explicit)] - internal struct Instruction - { - [FieldOffset(0)] internal OpCode OpCode; - [FieldOffset(4)] internal double Number; - [FieldOffset(4)] internal int NumVal; - [FieldOffset(8)] internal int NumVal2; - [FieldOffset(16)] object _object; - - internal SymbolRef Symbol - { - get => _object as SymbolRef; - set => _object = value; - } - - internal SymbolRef[] SymbolList - { - get => _object as SymbolRef[]; - set => _object = value; - } - - internal string String - { - get => _object as string; - set => _object = value; - } - - internal Annotation[] Annotations - { - get => _object as Annotation[]; - set => _object = value; - } - - - public override string ToString() - { - string append = this.OpCode.ToString().ToUpperInvariant(); - - int usage = (int)OpCode.GetFieldUsage(); - - if (usage != 0) - append += GenSpaces(); - - if ((this.OpCode == VM.OpCode.Meta) ||((usage & ((int)InstructionFieldUsage.NumValAsCodeAddress)) == (int)InstructionFieldUsage.NumValAsCodeAddress)) - append += " " + NumVal.ToString("X8"); - else if ((usage & ((int)InstructionFieldUsage.NumVal)) != 0) - append += " " + NumVal.ToString(); - else if ((usage & ((int)InstructionFieldUsage.Number)) != 0) - append += " " + Number.ToString(); - if ((usage & ((int)InstructionFieldUsage.NumVal2)) != 0) - append += " " + NumVal2.ToString(); - - if ((usage & ((int)InstructionFieldUsage.String)) != 0) - append += " " + (String == null ? "" : DynValue.NewString(String).SerializeValue()); - - if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0) - append += " " + Symbol; - - if (((usage & ((int)InstructionFieldUsage.SymbolList)) != 0) && (SymbolList != null)) - append += " " + string.Join(",", SymbolList.Select(s => s.ToString()).ToArray()); - - if (((usage & ((int) InstructionFieldUsage.Annotations)) != 0) && (Annotations != null)) - append += " " + string.Join(",", Annotations.Select((x => x.ToString()))); - - return append; - } - - private string GenSpaces() - { - return new string(' ', 10 - this.OpCode.ToString().Length); - } - - internal void WriteBinary(BinDumpWriter wr, int baseAddress, Dictionary symbolMap) - { - wr.WriteByte((byte)this.OpCode); - - int usage = (int)OpCode.GetFieldUsage(); - - if ((usage & (int) InstructionFieldUsage.Number) == 0 - && (usage & (int) InstructionFieldUsage.NumVal2) == 0 && - (usage & (int) InstructionFieldUsage.NumVal) == 0 && - (usage & (int) InstructionFieldUsage.NumValAsCodeAddress) == 0 && - (NumVal != 0 || NumVal2 != 0)) - throw new Exception("NumVal usage"); - - if ((usage & ((int)InstructionFieldUsage.String)) == 0 && - (usage & ((int)InstructionFieldUsage.Symbol)) == 0 && - (usage & ((int)InstructionFieldUsage.SymbolList)) == 0 && - (usage & ((int)InstructionFieldUsage.Annotations)) == 0 && - _object != null) - { - throw new Exception("Object usage"); - } - - if ((usage & ((int) InstructionFieldUsage.Number)) == (int) InstructionFieldUsage.Number) - { - wr.WriteDouble(this.Number); - } - else - { - if ((usage & ((int) InstructionFieldUsage.NumValAsCodeAddress)) == - (int) InstructionFieldUsage.NumValAsCodeAddress) - wr.WriteVarInt32(this.NumVal - baseAddress); - else if ((usage & ((int) InstructionFieldUsage.NumVal)) != 0) - wr.WriteVarInt32(this.NumVal); - if ((usage & ((int) InstructionFieldUsage.NumVal2)) != 0) - wr.WriteVarInt32(this.NumVal2); - } - - if ((usage & ((int)InstructionFieldUsage.String)) != 0) - wr.WriteString(String); - - if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0) - WriteSymbol(wr, Symbol, symbolMap); - - if ((usage & ((int)InstructionFieldUsage.SymbolList)) != 0) - { - wr.WriteVarUInt32((uint)this.SymbolList.Length); - for (int i = 0; i < this.SymbolList.Length; i++) - WriteSymbol(wr, SymbolList[i], symbolMap); - } - - if ((usage & ((int) InstructionFieldUsage.Annotations)) != 0) - { - wr.WriteVarUInt32((uint)this.Annotations.Length); - for (int i = 0; i < Annotations.Length; i++) - { - wr.WriteString(Annotations[i].Name); - WriteDynValue(wr, Annotations[i].Value, true); - } - } - } - - private static void WriteSymbol(BinDumpWriter wr, SymbolRef symbolRef, Dictionary symbolMap) - { - int id = (symbolRef == null) ? 0 : symbolMap[symbolRef] + 1; - wr.WriteVarUInt32((uint)id); - } - - private static SymbolRef ReadSymbol(BinDumpReader rd, SymbolRef[] deserializedSymbols) - { - uint id = rd.ReadVarUInt32(); - - if (id < 1) return null; - return deserializedSymbols[id - 1]; - } - - static void WriteDynValue(BinDumpWriter wr, DynValue d, bool allowTable) - { - switch (d.Type) { - case DataType.Nil: - wr.WriteByte((byte)d.Type); - break; - case DataType.Void: - wr.WriteByte((byte)d.Type); - break; - case DataType.Boolean: - if(d.Boolean) wr.WriteByte((byte)DataType.Boolean | 0x80); - else wr.WriteByte((byte)DataType.Boolean); - break; - case DataType.String: - wr.WriteByte((byte)d.Type); - wr.WriteString(d.String); - break; - case DataType.Number: - wr.WriteByte((byte)d.Type); - wr.WriteDouble(d.Number); - break; - case DataType.Table when allowTable: - wr.WriteByte((byte)d.Type); - WriteTable(wr, d.Table); - break; - case DataType.Table when !allowTable: - throw new Exception("Stored table key cannot be table"); - default: - throw new Exception("Can only store DynValue of string/number/bool/nil/table"); - } - } - - static void WriteTable(BinDumpWriter wr, Table t) - { - //this enumerates twice. not ideal - wr.WriteVarInt32(t.Pairs.Count()); - foreach (var p in t.Pairs) - { - WriteDynValue(wr, p.Key, false); - WriteDynValue(wr, p.Value, true); - } - } - - static DynValue ReadDynValue(BinDumpReader rd, bool allowTable) - { - var b = rd.ReadByte(); - var type = (DataType) (b & 0x7f); - switch (type) { - case DataType.Nil: - return DynValue.Nil; - case DataType.Void: - return DynValue.Void; - case DataType.Boolean: - if ((b & 0x80) == 0x80) return DynValue.True; - return DynValue.False; - case DataType.String: - return DynValue.NewString(rd.ReadString()); - case DataType.Number: - return DynValue.NewNumber(rd.ReadDouble()); - case DataType.Table when allowTable: - return ReadTable(rd); - default: - throw new InternalErrorException("Invalid DynValue storage in bytecode"); - } - } - - static DynValue ReadTable(BinDumpReader rd) - { - var d = DynValue.NewPrimeTable(); - var table = d.Table; - var c = rd.ReadVarInt32(); - for (int i = 0; i < c; i++) { - table.Set(ReadDynValue(rd, false), ReadDynValue(rd, true)); - } - return d; - } - - internal static Instruction ReadBinary(BinDumpReader rd, int baseAddress, Table envTable, SymbolRef[] deserializedSymbols) - { - Instruction that = new Instruction(); - - that.OpCode = (OpCode)rd.ReadByte(); - - int usage = (int)that.OpCode.GetFieldUsage(); - - if ((usage & ((int) InstructionFieldUsage.Number)) == (int)InstructionFieldUsage.Number) - { - that.Number = rd.ReadDouble(); - } - else - { - if ((usage & ((int) InstructionFieldUsage.NumValAsCodeAddress)) == - (int) InstructionFieldUsage.NumValAsCodeAddress) - that.NumVal = rd.ReadVarInt32() + baseAddress; - else if ((usage & ((int) InstructionFieldUsage.NumVal)) != 0) - that.NumVal = rd.ReadVarInt32(); - - if ((usage & ((int) InstructionFieldUsage.NumVal2)) != 0) - that.NumVal2 = rd.ReadVarInt32(); - } - - if ((usage & ((int)InstructionFieldUsage.String)) != 0) - that.String = rd.ReadString(); - - if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0) - that.Symbol = ReadSymbol(rd, deserializedSymbols); - - if ((usage & ((int)InstructionFieldUsage.SymbolList)) != 0) - { - int len = (int)rd.ReadVarUInt32(); - that.SymbolList = new SymbolRef[len]; - - for (int i = 0; i < that.SymbolList.Length; i++) - that.SymbolList[i] = ReadSymbol(rd, deserializedSymbols); - } - - if ((usage & ((int) InstructionFieldUsage.Annotations)) != 0) - { - int len = (int) rd.ReadVarUInt32(); - that.Annotations = new Annotation[len]; - for (int i = 0; i < that.Annotations.Length; i++) - { - that.Annotations[i] = new Annotation(rd.ReadString(), ReadDynValue(rd, true)); - } - } - - - return that; - } - - internal void GetSymbolReferences(out SymbolRef[] symbolList, out SymbolRef symbol) - { - int usage = (int)OpCode.GetFieldUsage(); - - symbol = null; - symbolList = null; - - if ((usage & ((int)InstructionFieldUsage.Symbol)) != 0) - symbol = this.Symbol; - - if ((usage & ((int)InstructionFieldUsage.SymbolList)) != 0) - symbolList = this.SymbolList; - } - } -} diff --git a/src/MoonSharp.Interpreter/Execution/VM/OpCodeMetadataType.cs b/src/MoonSharp.Interpreter/Execution/VM/OpCodeMetadataType.cs deleted file mode 100644 index 8b5dd3fd..00000000 --- a/src/MoonSharp.Interpreter/Execution/VM/OpCodeMetadataType.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MoonSharp.Interpreter.Execution.VM -{ - public enum OpCodeMetadataType - { - ChunkEntrypoint, - FunctionEntrypoint, - } -} diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_BinaryDump.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_BinaryDump.cs deleted file mode 100644 index 5ddd7831..00000000 --- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_BinaryDump.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using MoonSharp.Interpreter.Debugging; -using MoonSharp.Interpreter.IO; - -namespace MoonSharp.Interpreter.Execution.VM -{ - sealed partial class Processor - { - const ulong DUMP_CHUNK_MAGIC = 0x0A04504D55444342; // "BCDUMP^D\n" - const byte DUMP_CHUNK_VERSION = 0x01; //version - - internal static bool IsDumpStream(Stream stream) - { - if (stream.Length >= 8) - { - using (BinaryReader br = new BinaryReader(stream, Encoding.UTF8, true)) - { - ulong magic = br.ReadUInt64(); - stream.Seek(-8, SeekOrigin.Current); - return magic == DUMP_CHUNK_MAGIC; - } - } - return false; - } - - internal string DumpString(int baseAddress) - { - Instruction? meta = FindMeta(ref baseAddress); - if (meta == null) - throw new ArgumentException("baseAddress"); - var builder = new StringBuilder(); - for (int i = 0; i <= meta.Value.NumVal; i++) - { - builder.AppendLine(m_RootChunk.Code[baseAddress + i].ToString()); - } - return builder.ToString(); - } - - internal int Dump(Stream stream, int baseAddress, bool hasUpvalues, bool writeSourceRefs) - { - var bw = new BinDumpWriter(stream); - - Dictionary symbolMap = new Dictionary(); - - Instruction? meta = FindMeta(ref baseAddress); - - if (meta == null) - throw new ArgumentException("baseAddress"); - - bw.WriteUInt64(DUMP_CHUNK_MAGIC); - bw.WriteByte(DUMP_CHUNK_VERSION); - bw.WriteBoolean(hasUpvalues); - bw.WriteVarUInt32((uint) meta.Value.NumVal); - - for (int i = 0; i <= meta.Value.NumVal; i++) - { - SymbolRef[] symbolList; - SymbolRef symbol; - - m_RootChunk.Code[baseAddress + i].GetSymbolReferences(out symbolList, out symbol); - - if (symbol != null) - AddSymbolToMap(symbolMap, symbol); - - if (symbolList != null) - foreach (var s in symbolList) - AddSymbolToMap(symbolMap, s); - } - - foreach (SymbolRef sr in symbolMap.Keys.ToArray()) - { - if (sr.i_Env != null) - AddSymbolToMap(symbolMap, sr.i_Env); - } - - SymbolRef[] allSymbols = new SymbolRef[symbolMap.Count]; - - foreach (KeyValuePair pair in symbolMap) - { - allSymbols[pair.Value] = pair.Key; - } - - bw.WriteVarUInt32((uint) symbolMap.Count); - - foreach (SymbolRef sym in allSymbols) - sym.WriteBinary(bw); - - foreach (SymbolRef sym in allSymbols) - sym.WriteBinaryEnv(bw, symbolMap); - - for (int i = 0; i <= meta.Value.NumVal; i++) - m_RootChunk.Code[baseAddress + i].WriteBinary(bw, baseAddress, symbolMap); - for (int i = 0; i <= meta.Value.NumVal; i++) - { - if(m_RootChunk.SourceRefs[baseAddress + i] == null || !writeSourceRefs) bw.WriteByte(0); - else if(i != 0 && m_RootChunk.SourceRefs[baseAddress + i] == m_RootChunk.SourceRefs[baseAddress + i - 1]) bw.WriteByte(1); - else - { - bw.WriteByte(2); - m_RootChunk.SourceRefs[baseAddress + i].WriteBinary(bw); - } - } - - - return meta.Value.NumVal + baseAddress + 1; - } - - private void AddSymbolToMap(Dictionary symbolMap, SymbolRef s) - { - if (!symbolMap.ContainsKey(s)) - symbolMap.Add(s, symbolMap.Count); - } - - internal int Undump(Stream stream, int sourceID, Table envTable, out bool hasUpvalues) - { - int baseAddress = m_RootChunk.Code.Count; - SourceRef sourceRef = new SourceRef(sourceID, 0, 0, 0, 0, false); - - var br = new BinDumpReader(stream); - ulong headerMark = br.ReadUInt64(); - - if (headerMark != DUMP_CHUNK_MAGIC) - throw new ArgumentException("Not a MoonSharp chunk"); - - int version = br.ReadByte(); - - if (version != DUMP_CHUNK_VERSION) - throw new ArgumentException("Invalid version"); - - hasUpvalues = br.ReadBoolean(); - - int len = (int)br.ReadVarUInt32(); - - int numSymbs = (int)br.ReadVarUInt32(); - SymbolRef[] allSymbs = new SymbolRef[numSymbs]; - - for (int i = 0; i < numSymbs; i++) - allSymbs[i] = SymbolRef.ReadBinary(br); - - for (int i = 0; i < numSymbs; i++) - allSymbs[i].ReadBinaryEnv(br, allSymbs); - - for (int i = 0; i <= len; i++) { - Instruction I = Instruction.ReadBinary(br, baseAddress, envTable, allSymbs); - m_RootChunk.Code.Add(I); - } - for (int i = 0; i <= len; i++) - { - var c = br.ReadByte(); - if(c == 0) m_RootChunk.SourceRefs.Add(sourceRef); - else if (c == 1) m_RootChunk.SourceRefs.Add(m_RootChunk.SourceRefs[m_RootChunk.SourceRefs.Count - 1]); - else m_RootChunk.SourceRefs.Add(SourceRef.ReadBinary(br, sourceID)); - } - - return baseAddress; - } - } -} diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs deleted file mode 100644 index 6d8e608f..00000000 --- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_InstructionLoop.cs +++ /dev/null @@ -1,1681 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using MoonSharp.Interpreter.DataStructs; -using MoonSharp.Interpreter.Debugging; -using MoonSharp.Interpreter.Interop; - -namespace MoonSharp.Interpreter.Execution.VM -{ - sealed partial class Processor - { - const int YIELD_SPECIAL_TRAP = -99; - const int YIELD_SPECIAL_AWAIT = -100; - - internal long AutoYieldCounter = 0; - - private DynValue Processing_Loop(int instructionPtr, bool canAwait = false) - { - // This is the main loop of the processor, has a weird control flow and needs to be as fast as possible. - // This sentence is just a convoluted way to say "don't complain about gotos". - - long executedInstructions = 0; - bool canAutoYield = (AutoYieldCounter > 0) && m_CanYield && (this.State != CoroutineState.Main); - - repeat_execution: - - try - { - while (true) - { - Instruction i = m_RootChunk.Code[instructionPtr]; - int currentPtr = instructionPtr; - if (m_Debug.DebuggerAttached != null) - { - ListenDebugger(i, instructionPtr); - } - - ++executedInstructions; - - if (canAutoYield && executedInstructions > AutoYieldCounter) - { - m_SavedInstructionPtr = instructionPtr; - return DynValue.NewForcedYieldReq(); - } - - ++instructionPtr; - - switch (i.OpCode) - { - case OpCode.Nop: - case OpCode.Debug: - case OpCode.Meta: - case OpCode.Annot: - break; - case OpCode.Pop: - m_ValueStack.RemoveLast(i.NumVal); - break; - case OpCode.Copy: - m_ValueStack.Push(m_ValueStack.Peek(i.NumVal)); - break; - case OpCode.CopyValue: - m_ValueStack.Push(GetStoreValue(i)); - break; - case OpCode.Swap: - ExecSwap(i); - break; - case OpCode.PushNil: - m_ValueStack.Push(DynValue.Nil); - break; - case OpCode.PushTrue: - m_ValueStack.Push(DynValue.True); - break; - case OpCode.PushFalse: - m_ValueStack.Push(DynValue.False); - break; - case OpCode.PushNumber: - m_ValueStack.Push(DynValue.NewNumber(i.Number)); - break; - case OpCode.PushString: - m_ValueStack.Push(DynValue.NewString(i.String)); - break; - case OpCode.BNot: - ExecBNot(i); - break; - case OpCode.BAnd: - ExecBAnd(i); - break; - case OpCode.BOr: - ExecBOr(i); - break; - case OpCode.BXor: - ExecBXor(i); - break; - case OpCode.BLShift: - ExecBLShift(i); - break; - case OpCode.BRShiftA: - ExecBRShiftA(i); - break; - case OpCode.BRShiftL: - ExecBRShiftL(i); - break; - case OpCode.Add: - instructionPtr = ExecAdd(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.AddStr: - instructionPtr = ExecAddStr(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Concat: - instructionPtr = ExecConcat(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Neg: - instructionPtr = ExecNeg(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Sub: - instructionPtr = ExecSub(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Mul: - instructionPtr = ExecMul(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Div: - instructionPtr = ExecDiv(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Mod: - instructionPtr = ExecMod(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Power: - instructionPtr = ExecPower(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Eq: - instructionPtr = ExecEq(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.LessEq: - instructionPtr = ExecLessEq(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Less: - instructionPtr = ExecLess(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Len: - instructionPtr = ExecLen(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Call: - case OpCode.ThisCall: - instructionPtr = Internal_ExecCall(canAwait, i.NumVal, instructionPtr, null, null, i.OpCode == OpCode.ThisCall, i.String); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - if (instructionPtr == YIELD_SPECIAL_AWAIT) goto yield_to_await; - break; - case OpCode.Scalar: - m_ValueStack.Push(m_ValueStack.Pop().ToScalar()); - break; - case OpCode.CloseUp: - { - ref var csi = ref m_ExecutionStack.Peek(); - if (csi.OpenClosures == null) break; - for (int j = csi.OpenClosures.Count - 1; j >= 0; j--) { - if (csi.OpenClosures[j].Index == csi.BasePointer + i.NumVal) - { - csi.OpenClosures[j].Close(); - csi.OpenClosures.RemoveAt(j); - } - } - break; - } - case OpCode.Not: - ExecNot(i); - break; - case OpCode.CNot: - ExecCNot(i); - break; - case OpCode.JfOrPop: - case OpCode.JtOrPop: - instructionPtr = ExecShortCircuitingOperator(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.JNil: - { - DynValue v = m_ValueStack.Pop().ToScalar(); - - if (v.Type == DataType.Nil || v.Type == DataType.Void) - instructionPtr = i.NumVal; - } - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.JNilChk: - { - if(m_ValueStack.Peek().IsNil()) - instructionPtr = i.NumVal; - } - break; - case OpCode.Jf: - instructionPtr = JumpBool(i, false, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Jt: - instructionPtr = JumpBool(i, true, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.Jump: - instructionPtr = i.NumVal; - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.MkTuple: - ExecMkTuple(i); - break; - case OpCode.Clean: - ClearBlockData(i); - break; - case OpCode.Closure: - ExecClosure(i); - break; - case OpCode.BeginFn: - ExecBeginFn(i); - break; - case OpCode.ToBool: - { - ref var top = ref m_ValueStack.Peek(); - top = DynValue.NewBoolean(top.CastToBool()); - break; - } - case OpCode.StrFormat: - ExecStrFormat(i); - break; - case OpCode.Args: - ExecArgs(i); - break; - case OpCode.Ret: - instructionPtr = ExecRet(i, currentPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - if (instructionPtr < 0) - goto return_to_native_code; - break; - case OpCode.Incr: - ExecIncr(i); - break; - case OpCode.JFor: - instructionPtr = ExecJFor(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.NewTable: - if (i.NumVal == 0) - m_ValueStack.Push(DynValue.NewTable(this.m_Script)); - else - m_ValueStack.Push(DynValue.NewPrimeTable()); - break; - case OpCode.IterPrep: - ExecIterPrep(i); - break; - case OpCode.IterUpd: - ExecIterUpd(i); - break; - case OpCode.ExpTuple: - ExecExpTuple(i); - break; - case OpCode.Local: - var scope = m_ExecutionStack.Peek().BasePointer; - m_ValueStack.Push(m_ValueStack[scope + i.NumVal]); - break; - case OpCode.Upvalue: - { - var cs = m_ExecutionStack.Peek().ClosureScope; - m_ValueStack.Push(cs[i.NumVal].Value()); - break; - } - case OpCode.StoreUpv: - ExecStoreUpv(i); - break; - case OpCode.StoreLcl: - ExecStoreLcl(i); - break; - case OpCode.TblInitN: - ExecTblInitN(i); - break; - case OpCode.TblInitI: - ExecTblInitI(i); - break; - case OpCode.Index: - case OpCode.IndexN: - case OpCode.IndexL: - instructionPtr = ExecIndex(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.IndexSet: - case OpCode.IndexSetN: - case OpCode.IndexSetL: - instructionPtr = ExecIndexSet(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.NilCoalescing: - instructionPtr = ExecNilCoalescingAssignment(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.NilCoalescingInverse: - instructionPtr = ExecNilCoalescingAssignmentInverse(i, instructionPtr); - if (instructionPtr == YIELD_SPECIAL_TRAP) goto yield_to_calling_coroutine; - break; - case OpCode.JLclInit: - if(m_ValueStack[m_ExecutionStack.Peek().BasePointer + i.NumVal2].IsNotNil()) - instructionPtr = i.NumVal; - break; - case OpCode.Invalid: - throw new NotImplementedException(string.Format("Invalid opcode : {0}", i.String)); - default: - throw new NotImplementedException(string.Format("Execution for {0} not implented yet!", i.OpCode)); - } - } - - yield_to_calling_coroutine: - - DynValue yieldRequest = m_ValueStack.Pop().ToScalar(); - - if (m_CanYield) - return yieldRequest; - else if (this.State == CoroutineState.Main) - throw ScriptRuntimeException.CannotYieldMain(); - else - throw ScriptRuntimeException.CannotYield(); - - yield_to_await: - DynValue awaitRequest = m_ValueStack.Pop().ToScalar(); - return awaitRequest; - - } - catch (InterpreterException ex) - { - FillDebugData(ex, instructionPtr); - - if (!(ex is ScriptRuntimeException)) - { - ex.Rethrow(); - throw; - } - - if (m_Debug.DebuggerAttached != null) - { - if (m_Debug.DebuggerAttached.SignalRuntimeException((ScriptRuntimeException)ex)) - { - if (instructionPtr >= 0 && instructionPtr < this.m_RootChunk.Code.Count) - { - ListenDebugger(m_RootChunk.Code[instructionPtr], instructionPtr); - } - } - } - - for (int i = 0; i < m_ExecutionStack.Count; i++) - { - var c = m_ExecutionStack.Peek(i); - - if (c.ErrorHandlerBeforeUnwind.IsNotNil()) - ex.DecoratedMessage = PerformMessageDecorationBeforeUnwind(c.ErrorHandlerBeforeUnwind, ex.DecoratedMessage, GetCurrentSourceRef(instructionPtr)); - } - - - while (m_ExecutionStack.Count > 0) - { - CallStackItem csi = PopToBasePointer(); - - if (csi.ErrorHandler != null) - { - instructionPtr = csi.ReturnAddress; - - if (csi.ClrFunction == null) - { - var argscnt = (int)(m_ValueStack.Pop().Number); - m_ValueStack.RemoveLast(argscnt + 1); - } - - var cbargs = new DynValue[] { DynValue.NewString(ex.DecoratedMessage) }; - - DynValue handled = csi.ErrorHandler.Invoke(new ScriptExecutionContext(this, csi.ErrorHandler, GetCurrentSourceRef(instructionPtr)), cbargs); - - m_ValueStack.Push(handled); - - goto repeat_execution; - } - else if ((csi.Flags & CallStackItemFlags.EntryPoint) != 0) - { - ex.Rethrow(); - throw; - } - } - - ex.Rethrow(); - throw; - } - - return_to_native_code: - return m_ValueStack.Pop(); - - - } - - - internal string PerformMessageDecorationBeforeUnwind(DynValue messageHandler, string decoratedMessage, SourceRef sourceRef) - { - try - { - DynValue[] args = new DynValue[] { DynValue.NewString(decoratedMessage) }; - DynValue ret = DynValue.Nil; - - if (messageHandler.Type == DataType.Function) - { - ret = this.Call(messageHandler, args); - } - else if (messageHandler.Type == DataType.ClrFunction) - { - ScriptExecutionContext ctx = new ScriptExecutionContext(this, messageHandler.Callback, sourceRef); - ret = messageHandler.Callback.Invoke(ctx, args); - } - else - { - throw new ScriptRuntimeException("error handler not set to a function"); - } - - string newmsg = ret.ToPrintString(); - if (newmsg != null) - return newmsg; - } - catch (ScriptRuntimeException innerEx) - { - return innerEx.Message + "\n" + decoratedMessage; - } - - return decoratedMessage; - } - - - - private void AssignLocal(SymbolRef symref, DynValue value) - { - var stackframe = m_ExecutionStack.Peek(); - m_ValueStack[stackframe.LocalBase + symref.i_Index] = value; - } - - private void ExecStoreLcl(Instruction i) - { - DynValue value = GetStoreValue(i); - SymbolRef symref = i.Symbol; - - AssignLocal(symref, value); - } - - private void ExecStoreUpv(Instruction i) - { - DynValue value = GetStoreValue(i); - SymbolRef symref = i.Symbol; - - var stackframe = m_ExecutionStack.Peek(); - - if(stackframe.ClosureScope[symref.i_Index] == null) - stackframe.ClosureScope[symref.i_Index] = Upvalue.NewNil(); - - stackframe.ClosureScope[symref.i_Index].Value() = value; - } - - private void ExecSwap(Instruction i) - { - DynValue v1 = m_ValueStack.Peek(i.NumVal); - DynValue v2 = m_ValueStack.Peek(i.NumVal2); - - m_ValueStack.Set(i.NumVal, v2); - m_ValueStack.Set(i.NumVal2, v1); - } - - - private DynValue GetStoreValue(Instruction i) - { - int stackofs = i.NumVal; - int tupleidx = i.NumVal2; - - ref DynValue v = ref m_ValueStack.Peek(stackofs); - - if (v.Type == DataType.Tuple) - { - return (tupleidx < v.Tuple.Length) ? v.Tuple[tupleidx] : DynValue.Nil; - } - else - { - return (tupleidx == 0) ? v : DynValue.Nil; - } - } - - private void ExecClosure(Instruction i) - { - Closure c = new Closure(this.m_Script, i.NumVal, i.SymbolList, FindAnnotations(i.NumVal), - i.SymbolList.Select(s => this.GetUpvalueSymbol(s)).ToList()); - m_ValueStack.Push(DynValue.NewClosure(c)); - } - - private Upvalue GetUpvalueSymbol(SymbolRef s) - { - if (s.Type == SymbolRefType.Local) - { - ref var ex = ref m_ExecutionStack.Peek(); - for (int i = 0; i < ex.OpenClosures?.Count; i++) { - if (ex.OpenClosures[i].Index == ex.LocalBase + s.i_Index) return ex.OpenClosures[i]; - } - var upval = new Upvalue(m_ValueStack, ex.LocalBase + s.i_Index); - - ex.OpenClosures ??= new List(); - ex.OpenClosures.Add(upval); - return upval; - } - else if (s.Type == SymbolRefType.Upvalue) - return m_ExecutionStack.Peek().ClosureScope[s.i_Index]; - else - throw new Exception("unsupported symbol type"); - } - - private void ExecMkTuple(Instruction i) - { - Slice slice = new Slice(m_ValueStack, m_ValueStack.Count - i.NumVal, i.NumVal, false); - - var v = Internal_AdjustTuple(slice); - - m_ValueStack.RemoveLast(i.NumVal); - - m_ValueStack.Push(DynValue.NewTuple(v)); - } - - private void ExecIterUpd(Instruction i) - { - DynValue v = m_ValueStack.Peek(0); - DynValue t = m_ValueStack.Peek(1); - t.Tuple[2] = v; - } - - private void ExecExpTuple(Instruction i) - { - DynValue t = m_ValueStack.Peek(i.NumVal); - - if (t.Type == DataType.Tuple) - { - for (int idx = 0; idx < t.Tuple.Length; idx++) - m_ValueStack.Push(t.Tuple[idx]); - } - else - { - m_ValueStack.Push(t); - } - - } - - private void ExecIterPrep(Instruction i) - { - DynValue v = m_ValueStack.Pop(); - - if (v.Type != DataType.Tuple) - { - v = DynValue.NewTuple(v, DynValue.Nil, DynValue.Nil); - } - - DynValue f = v.Tuple.Length >= 1 ? v.Tuple[0] : DynValue.Nil; - DynValue s = v.Tuple.Length >= 2 ? v.Tuple[1] : DynValue.Nil; - DynValue var = v.Tuple.Length >= 3 ? v.Tuple[2] : DynValue.Nil; - - // MoonSharp additions - given f, s, var - // 1) if f is not a function and has a __iterator metamethod, call __iterator to get the triplet - // 2) if f is a table with no __call metamethod, use a default table iterator - - if (f.Type != DataType.Function && f.Type != DataType.ClrFunction) - { - DynValue meta = this.GetMetamethod(f, "__iterator"); - - if (!meta.IsNil()) - { - if (meta.Type != DataType.Tuple) - v = this.GetScript().Call(meta, f, s, var); - else - v = meta; - - f = v.Tuple.Length >= 1 ? v.Tuple[0] : DynValue.Nil; - s = v.Tuple.Length >= 2 ? v.Tuple[1] : DynValue.Nil; - var = v.Tuple.Length >= 3 ? v.Tuple[2] : DynValue.Nil; - - m_ValueStack.Push(DynValue.NewTuple(f, s, var)); - return; - } - else if (f.Type == DataType.Table) - { - DynValue callmeta = this.GetMetamethod(f, "__call"); - - if (callmeta.IsNil()) - { - m_ValueStack.Push(EnumerableWrapper.ConvertTable(f.Table)); - return; - } - } - } - - m_ValueStack.Push(DynValue.NewTuple(f, s, var)); - } - - - private int ExecJFor(Instruction i, int instructionPtr) - { - double val = m_ValueStack.Peek(0).AssertNumber(1); - double step = m_ValueStack.Peek(1).AssertNumber(2); - double stop = m_ValueStack.Peek(2).AssertNumber(3); - - bool whileCond = (step > 0) ? val <= stop : val >= stop; - - if (!whileCond) - return i.NumVal; - else - return instructionPtr; - } - - - - private void ExecIncr(Instruction i) - { - ref DynValue top = ref m_ValueStack.Peek(0); - DynValue btm = m_ValueStack.Peek(i.NumVal); - - top = DynValue.NewNumber(top.Number + btm.Number); - } - - - private void ExecCNot(Instruction i) - { - DynValue v = m_ValueStack.Pop().ToScalar(); - DynValue not = m_ValueStack.Pop().ToScalar(); - - if (not.Type != DataType.Boolean) - throw new InternalErrorException("CNOT had non-bool arg"); - - if (not.CastToBool()) - m_ValueStack.Push(DynValue.NewBoolean(!(v.CastToBool()))); - else - m_ValueStack.Push(DynValue.NewBoolean(v.CastToBool())); - } - - private void ExecNot(Instruction i) - { - DynValue v = m_ValueStack.Pop().ToScalar(); - m_ValueStack.Push(DynValue.NewBoolean(!(v.CastToBool()))); - } - - private void ExecBeginFn(Instruction i) - { - ref CallStackItem cur = ref m_ExecutionStack.Peek(); - - cur.Debug_Symbols = i.SymbolList; - cur.LocalCount = i.NumVal; - cur.LocalBase = m_ValueStack.Reserve(i.NumVal); - - ClearBlockData(i); - } - - private CallStackItem PopToBasePointer() - { - var csi = m_ExecutionStack.Pop(); - if (csi.OpenClosures != null) - foreach(var closure in csi.OpenClosures) closure.Close(); - if (csi.BasePointer >= 0) - m_ValueStack.CropAtCount(csi.BasePointer); - return csi; - } - - private int PopExecStackAndCheckVStack(int vstackguard) - { - var xs = m_ExecutionStack.Pop(); - if (vstackguard != xs.BasePointer) - throw new InternalErrorException("StackGuard violation"); - - return xs.ReturnAddress; - } - - private IList CreateArgsListForFunctionCall(int numargs, int offsFromTop) - { - if (numargs == 0) return Array.Empty(); - - DynValue lastParam = m_ValueStack.Peek(offsFromTop); - - if (lastParam.Type == DataType.Tuple && lastParam.Tuple.Length > 1) - { - List values = new List(); - - for (int idx = 0; idx < numargs - 1; idx++) - values.Add(m_ValueStack.Peek(numargs - idx - 1 + offsFromTop)); - - for (int idx = 0; idx < lastParam.Tuple.Length; idx++) - values.Add(lastParam.Tuple[idx]); - - return values; - } - else - { - return new Slice(m_ValueStack, m_ValueStack.Count - numargs - offsFromTop, numargs, false); - } - } - - - private void ExecArgs(Instruction I) - { - int localCount = m_ExecutionStack.Peek().LocalCount; - int numargs = (int)m_ValueStack.Peek(localCount).Number; - // unpacks last tuple arguments to simplify a lot of code down under - var argsList = CreateArgsListForFunctionCall(numargs, 1 + localCount); - - for (int i = 0; i < I.SymbolList.Length; i++) - { - if (i >= argsList.Count) - { - this.AssignLocal(I.SymbolList[i], DynValue.Nil); - } - else if ((i == I.SymbolList.Length - 1) && (I.SymbolList[i].i_Name == WellKnownSymbols.VARARGS)) - { - int len = argsList.Count - i; - DynValue[] varargs = new DynValue[len]; - - for (int ii = 0; ii < len; ii++, i++) - { - varargs[ii] = argsList[i].ToScalar(); - } - - this.AssignLocal(I.SymbolList[I.SymbolList.Length - 1], DynValue.NewTuple(Internal_AdjustTuple(varargs))); - } - else - { - this.AssignLocal(I.SymbolList[i], argsList[i].ToScalar()); - } - } - } - - - - - private int Internal_ExecCall(bool canAwait, int argsCount, int instructionPtr, CallbackFunction handler = null, - CallbackFunction continuation = null, bool thisCall = false, string debugText = null, DynValue unwindHandler = default) - { - DynValue fn = m_ValueStack.Peek(argsCount); - CallStackItemFlags flags = (thisCall ? CallStackItemFlags.MethodCall : CallStackItemFlags.None); - - // if TCO threshold reached - if ((m_ExecutionStack.Count > this.m_Script.Options.TailCallOptimizationThreshold && m_ExecutionStack.Count > 1) - || (m_ValueStack.Count > this.m_Script.Options.TailCallOptimizationThreshold && m_ValueStack.Count > 1)) - { - // and the "will-be" return address is valid (we don't want to crash here) - if (instructionPtr >= 0 && instructionPtr < this.m_RootChunk.Code.Count) - { - Instruction I = this.m_RootChunk.Code[instructionPtr]; - - // and we are followed *exactly* by a RET 1 - if (I.OpCode == OpCode.Ret && I.NumVal == 1) - { - ref CallStackItem csi = ref m_ExecutionStack.Peek(); - - // if the current stack item has no "odd" things pending and neither has the new coming one.. - if (csi.ClrFunction == null && csi.Continuation == null && csi.ErrorHandler == null - && csi.ErrorHandlerBeforeUnwind.IsNil() && continuation == null && unwindHandler.IsNil() && handler == null) - { - instructionPtr = PerformTCO(instructionPtr, argsCount); - flags |= CallStackItemFlags.TailCall; - } - } - } - } - - - - if (fn.Type == DataType.ClrFunction) - { - //IList args = new Slice(m_ValueStack, m_ValueStack.Count - argsCount, argsCount, false); - IList args = CreateArgsListForFunctionCall(argsCount, 0); - // we expand tuples before callbacks - // args = DynValue.ExpandArgumentsToList(args); - - // instructionPtr - 1: instructionPtr already points to the next instruction at this moment - // but we need the current instruction here - SourceRef sref = GetCurrentSourceRef(instructionPtr - 1); - - m_ExecutionStack.Push(new CallStackItem() - { - ClrFunction = fn.Callback, - ReturnAddress = instructionPtr, - CallingSourceRef = sref, - BasePointer = -1, - ErrorHandler = handler, - Continuation = continuation, - ErrorHandlerBeforeUnwind = unwindHandler, - Flags = flags, - }); - - var ret = fn.Callback.Invoke(new ScriptExecutionContext(this, fn.Callback, sref) { CanAwait = canAwait }, args, isMethodCall: thisCall); - m_ValueStack.RemoveLast(argsCount + 1); - if (m_Script.Options.AutoAwait && - ret.Type == DataType.UserData && - ret.UserData?.Object is TaskWrapper tw) - { - ret = tw.@await( - new ScriptExecutionContext(this, fn.Callback, sref) {CanAwait = canAwait}, null); - } - m_ValueStack.Push(ret); - - m_ExecutionStack.Pop(); - - return Internal_CheckForTailRequests(canAwait, instructionPtr); - } - else if (fn.Type == DataType.Function) - { - m_ValueStack.Push(DynValue.NewNumber(argsCount)); - m_ExecutionStack.Push(new CallStackItem() - { - BasePointer = m_ValueStack.Count, - ReturnAddress = instructionPtr, - Debug_EntryPoint = fn.Function.EntryPointByteCodeLocation, - CallingSourceRef = GetCurrentSourceRef(instructionPtr - 1), // See right above in GetCurrentSourceRef(instructionPtr - 1) - ClosureScope = fn.Function.ClosureContext, - ErrorHandler = handler, - Continuation = continuation, - ErrorHandlerBeforeUnwind = unwindHandler, - Flags = flags, - }); - return fn.Function.EntryPointByteCodeLocation; - } - - // fallback to __call metamethod - var m = GetMetamethod(fn, "__call"); - - if (m.IsNotNil()) - { - DynValue[] tmp = new DynValue[argsCount + 1]; - for (int i = 0; i < argsCount + 1; i++) - tmp[i] = m_ValueStack.Pop(); - - m_ValueStack.Push(m); - - for (int i = argsCount; i >= 0; i--) - m_ValueStack.Push(tmp[i]); - - return Internal_ExecCall(canAwait, argsCount + 1, instructionPtr, handler, continuation); - } - - throw ScriptRuntimeException.AttemptToCallNonFunc(fn.Type, debugText); - } - - private int PerformTCO(int instructionPtr, int argsCount) - { - DynValue[] args = new DynValue[argsCount + 1]; - - // Remove all cur args and func ptr - for (int i = 0; i <= argsCount; i++) - args[i] = m_ValueStack.Pop(); - - // perform a fake RET - CallStackItem csi = PopToBasePointer(); - int retpoint = csi.ReturnAddress; - var argscnt = (int)(m_ValueStack.Pop().Number); - m_ValueStack.RemoveLast(argscnt + 1); - - // Re-push all cur args and func ptr - for (int i = argsCount; i >= 0; i--) - m_ValueStack.Push(args[i]); - - return retpoint; - } - - private int ExecNilCoalescingAssignment(Instruction i, int instructionPtr) - { - ref DynValue lhs = ref m_ValueStack.Peek(1); - if (lhs.IsNil()) - { - m_ValueStack.Set(1, m_ValueStack.Peek()); - } - - m_ValueStack.Pop(); - return instructionPtr; - } - - private int ExecNilCoalescingAssignmentInverse(Instruction i, int instructionPtr) - { - ref DynValue lhs = ref m_ValueStack.Peek(1); - if (lhs.IsNotNil()) - { - m_ValueStack.Set(1, m_ValueStack.Peek()); - } - - m_ValueStack.Pop(); - return instructionPtr; - } - - private int ExecRet(Instruction i, int currentPtr) - { - CallStackItem csi; - int retpoint = 0; - - if (i.NumVal == 0) - { - csi = PopToBasePointer(); - retpoint = csi.ReturnAddress; - var argscnt = (int)(m_ValueStack.Pop().Number); - m_ValueStack.RemoveLast(argscnt + 1); - m_ValueStack.Push(DynValue.Void); - } - else if (i.NumVal == 1) - { - var retval = m_ValueStack.Pop(); - csi = PopToBasePointer(); - retpoint = csi.ReturnAddress; - var argscnt = (int)(m_ValueStack.Pop().Number); - m_ValueStack.RemoveLast(argscnt + 1); - m_ValueStack.Push(retval); - retpoint = Internal_CheckForTailRequests(false, retpoint); - } - else - { - throw new InternalErrorException("RET supports only 0 and 1 ret val scenarios"); - } - - if (csi.Continuation != null) - m_ValueStack.Push(csi.Continuation.Invoke(new ScriptExecutionContext(this, csi.Continuation, m_RootChunk.SourceRefs[currentPtr]), - new DynValue[1] { m_ValueStack.Pop() })); - - return retpoint; - } - - - - private int Internal_CheckForTailRequests(bool canAwait, int instructionPtr) - { - DynValue tail = m_ValueStack.Peek(0); - - if (tail.Type == DataType.TailCallRequest) - { - m_ValueStack.Pop(); // discard tail call request - - TailCallData tcd = tail.TailCallData; - - m_ValueStack.Push(tcd.Function); - - for (int ii = 0; ii < tcd.Args.Length; ii++) - m_ValueStack.Push(tcd.Args[ii]); - - return Internal_ExecCall(canAwait, tcd.Args.Length, instructionPtr, tcd.ErrorHandler, tcd.Continuation, false, null, tcd.ErrorHandlerBeforeUnwind); - } - else if (tail.Type == DataType.YieldRequest) - { - m_SavedInstructionPtr = instructionPtr; - return YIELD_SPECIAL_TRAP; - } else if (tail.Type == DataType.AwaitRequest) - { - if (!canAwait) - throw new ScriptRuntimeException( - "Await Request happened when it shouldn't have. Internal state corruption?"); - m_SavedInstructionPtr = instructionPtr; - return YIELD_SPECIAL_AWAIT; - } - - - return instructionPtr; - } - - - - private int JumpBool(Instruction i, bool expectedValueForJump, int instructionPtr) - { - DynValue op = m_ValueStack.Pop().ToScalar(); - - if (op.CastToBool() == expectedValueForJump) - return i.NumVal; - - return instructionPtr; - } - - private int ExecShortCircuitingOperator(Instruction i, int instructionPtr) - { - bool expectedValToShortCircuit = i.OpCode == OpCode.JtOrPop; - - DynValue op = m_ValueStack.Peek().ToScalar(); - - if (op.CastToBool() == expectedValToShortCircuit) - { - return i.NumVal; - } - else - { - m_ValueStack.Pop(); - return instructionPtr; - } - } - - private void ExecBNot(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var ln)) - { - m_ValueStack.Set(0, DynValue.NewNumber(~(int)ln)); - } - else - { - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l); - } - } - - - private void ExecBAnd(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber((int)ln & (int)rn)); - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private void ExecBOr(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber((int)ln | (int)rn)); - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private void ExecBXor(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber((int)ln ^ (int)rn)); - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private void ExecBLShift(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber((int)ln << (int)rn)); - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private void ExecBRShiftA(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber((int)ln >> (int)rn)); - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private void ExecBRShiftL(Instruction i) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber((int)( - (uint)ln >> (int)rn - ))); - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - - private int ExecAdd(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(ln + rn)); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__add", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - bool ToConcatString(ref DynValue v, out string s, ref int metamethodCounter) - { - var sc = v.ToScalar(); - if (v.IsNil()) { - s = null; - return false; - } - if (v.Type == DataType.String) - { - s = v.String; - return true; - } - else if (v.Type == DataType.Boolean) - { - s = v.Boolean ? "true" : "false"; - return true; - } - else if (v.Type == DataType.Number) { - s = v.Number.ToString(); - return true; - } - - var m = GetMetamethod(v, "__tostring"); - if (!m.IsNil()) - { - if (metamethodCounter++ > 10) { - s = null; - return false; - } - var retval = Call(m, new[] {v}); - return ToConcatString(ref retval, out s, ref metamethodCounter); - } - else { - s = null; - return false; - } - } - - private void ExecStrFormat(Instruction i) - { - string[] formatValues = new string[i.NumVal]; - if (i.NumVal > 0) - { - for (int j = 0; j < i.NumVal; j++) - { - var off = (i.NumVal - j - 1); - int mCount = 0; - if (!ToConcatString(ref m_ValueStack.Peek(off), out formatValues[j], ref mCount)) - { - formatValues[j] = m_ValueStack.Peek(off).ToPrintString(); - } - } - } - m_ValueStack.RemoveLast(i.NumVal); - m_ValueStack.Set(0, DynValue.NewString(string.Format(m_ValueStack.Peek(0).String, formatValues))); - } - - private int ExecAddStr(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(ln + rn)); - return instructionPtr; - } - else if (m_ValueStack.Peek(1).Type == DataType.String || - m_ValueStack.Peek().Type == DataType.String) - { - int c1 = 0, c2 = 0; - if (!ToConcatString(ref m_ValueStack.Peek(), out var rhs, ref c1) || - !ToConcatString(ref m_ValueStack.Peek(1), out var lhs, ref c2)) - { - var l = m_ValueStack.Pop().ToScalar(); - var r = m_ValueStack.Pop().ToScalar(); - throw ScriptRuntimeException.ConcatOnNonString(l, r); - } - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewString(lhs + rhs)); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__add", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private int ExecSub(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(ln - rn)); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__sub", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - - private int ExecMul(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(ln * rn)); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mul", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private int ExecMod(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - var mod = ln - Math.Floor(ln / rn) * rn; - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(mod)); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mod", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - - private int ExecDiv(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(ln / rn)); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__div", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - } - private int ExecPower(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn) && - m_ValueStack.Peek(1).TryCastToNumber(out var ln)) - { - m_ValueStack.Pop(); - m_ValueStack.Set(0, DynValue.NewNumber(Math.Pow(ln,rn))); - return instructionPtr; - } - else - { - var r = m_ValueStack.Pop().ToScalar(); - var l = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__pow", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r); - } - - } - - private int ExecNeg(Instruction i, int instructionPtr) - { - if (m_ValueStack.Peek().TryCastToNumber(out var rn)) - { - m_ValueStack.Set(0, DynValue.NewNumber(-rn)); - return instructionPtr; - } - else - { - DynValue r = m_ValueStack.Pop().ToScalar(); - int ip = Internal_InvokeUnaryMetaMethod(r, "__unm", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ArithmeticOnNonNumber(r); - } - } - - - private int ExecEq(Instruction i, int instructionPtr) - { - DynValue r = m_ValueStack.Pop().ToScalar(); - DynValue l = m_ValueStack.Pop().ToScalar(); - - // first we do a brute force equals over the references - if (object.ReferenceEquals(r, l)) - { - m_ValueStack.Push(DynValue.True); - return instructionPtr; - } - - // then if they are userdatas, attempt meta - if (l.Type == DataType.UserData || r.Type == DataType.UserData) - { - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__eq", instructionPtr); - if (ip >= 0) return ip; - } - - // then if types are different, ret false - if (r.Type != l.Type) - { - if ((l.Type == DataType.Nil && r.Type == DataType.Void) || (l.Type == DataType.Void && r.Type == DataType.Nil)) - m_ValueStack.Push(DynValue.True); - else - m_ValueStack.Push(DynValue.False); - - return instructionPtr; - } - - // then attempt metatables for tables - if ((l.Type == DataType.Table) && (GetMetatable(l) != null) && (GetMetatable(l) == GetMetatable(r))) - { - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__eq", instructionPtr); - if (ip >= 0) return ip; - } - - // else perform standard comparison - m_ValueStack.Push(DynValue.NewBoolean(r.Equals(l))); - return instructionPtr; - } - - private int ExecLess(Instruction i, int instructionPtr) - { - DynValue r = m_ValueStack.Pop().ToScalar(); - DynValue l = m_ValueStack.Pop().ToScalar(); - - if (l.Type == DataType.Number && r.Type == DataType.Number) - { - m_ValueStack.Push(DynValue.NewBoolean(l.Number < r.Number)); - } - else if (l.Type == DataType.String && r.Type == DataType.String) - { - m_ValueStack.Push(DynValue.NewBoolean(l.String.CompareTo(r.String) < 0)); - } - else - { - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__lt", instructionPtr); - if (ip < 0) - throw ScriptRuntimeException.CompareInvalidType(l, r); - else - return ip; - } - - return instructionPtr; - } - - - private int ExecLessEq(Instruction i, int instructionPtr) - { - DynValue r = m_ValueStack.Pop().ToScalar(); - DynValue l = m_ValueStack.Pop().ToScalar(); - - if (l.Type == DataType.Number && r.Type == DataType.Number) - { - m_ValueStack.Push(DynValue.False); - m_ValueStack.Push(DynValue.NewBoolean(l.Number <= r.Number)); - } - else if (l.Type == DataType.String && r.Type == DataType.String) - { - m_ValueStack.Push(DynValue.False); - m_ValueStack.Push(DynValue.NewBoolean(l.String.CompareTo(r.String) <= 0)); - } - else - { - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__le", instructionPtr, DynValue.False); - if (ip < 0) - { - ip = Internal_InvokeBinaryMetaMethod(r, l, "__lt", instructionPtr, DynValue.True); - - if (ip < 0) - throw ScriptRuntimeException.CompareInvalidType(l, r); - else - return ip; - } - else - return ip; - } - - return instructionPtr; - } - - private int ExecLen(Instruction i, int instructionPtr) - { - DynValue r = m_ValueStack.Pop().ToScalar(); - - if (r.Type == DataType.String) - m_ValueStack.Push(DynValue.NewNumber(r.String.Length)); - else - { - int ip = Internal_InvokeUnaryMetaMethod(r, "__len", instructionPtr); - if (ip >= 0) - return ip; - else if (r.Type == DataType.Table) - m_ValueStack.Push(DynValue.NewNumber(r.Table.Length)); - - else throw ScriptRuntimeException.LenOnInvalidType(r); - } - - return instructionPtr; - } - - - private int ExecConcat(Instruction i, int instructionPtr) - { - DynValue r = m_ValueStack.Pop().ToScalar(); - DynValue l = m_ValueStack.Pop().ToScalar(); - - string rs = r.CastToString(); - string ls = l.CastToString(); - - if (rs != null && ls != null) - { - m_ValueStack.Push(DynValue.NewString(ls + rs)); - return instructionPtr; - } - else - { - int ip = Internal_InvokeBinaryMetaMethod(l, r, "__concat", instructionPtr); - if (ip >= 0) return ip; - else throw ScriptRuntimeException.ConcatOnNonString(l, r); - } - - } - - - private void ExecTblInitI(Instruction i) - { - // stack: tbl - val - DynValue val = m_ValueStack.Pop(); - DynValue tbl = m_ValueStack.Peek(); - - if (tbl.Type != DataType.Table) - throw new InternalErrorException("Unexpected type in table ctor : {0}", tbl); - - tbl.Table.InitNextArrayKeys(val, i.NumVal != 0); - } - - private void ExecTblInitN(Instruction i) - { - // stack: tbl - key - val - DynValue val = m_ValueStack.Pop(); - DynValue key = m_ValueStack.Pop(); - DynValue tbl = m_ValueStack.Peek(); - - if (tbl.Type != DataType.Table) - throw new InternalErrorException("Unexpected type in table ctor : {0}", tbl); - - tbl.Table.Set(key, val.ToScalar()); - } - - private int ExecIndexSet(Instruction i, int instructionPtr) - { - int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here - - // stack: vals.. - base - index - bool isNameIndex = i.OpCode == OpCode.IndexSetN; - bool isMultiIndex = (i.OpCode == OpCode.IndexSetL); - - DynValue originalIdx; - if (i.String != null) - originalIdx = DynValue.NewString(i.String); - else - originalIdx = m_ValueStack.Pop(); - DynValue idx = originalIdx.ToScalar(); - DynValue obj = m_ValueStack.Pop().ToScalar(); - var value = GetStoreValue(i); - DynValue h = DynValue.Nil; - - - while (nestedMetaOps > 0) - { - --nestedMetaOps; - - if (obj.Type == DataType.Table) - { - if (!isMultiIndex) - { - //Don't do check for __newindex if there is no metatable to begin with - if (obj.Table.MetaTable == null || !obj.Table.Get(idx).IsNil()) - { - obj.Table.Set(idx, value); - return instructionPtr; - } - } - - h = GetMetamethodRaw(obj, "__newindex"); - - if (h.IsNil()) - { - if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index a table. userdata expected"); - - obj.Table.Set(idx, value); - return instructionPtr; - } - } - else if (obj.Type == DataType.UserData) - { - UserData ud = obj.UserData; - - if (!ud.Descriptor.SetIndex(this.GetScript(), ud.Object, originalIdx, value, isNameIndex)) - { - throw ScriptRuntimeException.UserDataMissingField(ud.Descriptor.Name, idx.String); - } - - return instructionPtr; - } - else - { - h = GetMetamethodRaw(obj, "__newindex"); - - if (h.IsNil()) - throw ScriptRuntimeException.IndexType(obj); - } - - if (h.Type == DataType.Function || h.Type == DataType.ClrFunction) - { - if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index through metamethods. userdata expected"); - m_ValueStack.Pop(); // burn extra value ? - - m_ValueStack.Push(h); - m_ValueStack.Push(obj); - m_ValueStack.Push(idx); - m_ValueStack.Push(value); - return Internal_ExecCall(false, 3, instructionPtr); - } - else - { - obj = h; - h = DynValue.Nil; - } - } - throw ScriptRuntimeException.LoopInNewIndex(); - } - - private int ExecIndex(Instruction i, int instructionPtr) - { - int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here - - // stack: base - index - bool isNameIndex = i.OpCode == OpCode.IndexN; - - bool isMultiIndex = (i.OpCode == OpCode.IndexL); - - DynValue originalIdx; - if (i.String != null) - originalIdx = DynValue.NewString(i.String); - else - originalIdx = m_ValueStack.Pop(); - DynValue idx = originalIdx.ToScalar(); - DynValue obj = m_ValueStack.Pop().ToScalar(); - - DynValue h = DynValue.Nil; - - - while (nestedMetaOps > 0) - { - --nestedMetaOps; - - if (obj.Type == DataType.Table) - { - if (!isMultiIndex) - { - var v = obj.Table.Get(idx); - - if (!v.IsNil()) - { - m_ValueStack.Push(v); - return instructionPtr; - } - } - - h = GetMetamethodRaw(obj, "__index"); - - if (h.IsNil()) - { - if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index a table. userdata expected"); - - m_ValueStack.Push(DynValue.Nil); - return instructionPtr; - } - } - else if (obj.Type == DataType.UserData) - { - UserData ud = obj.UserData; - - var v = ud.Descriptor.Index(this.GetScript(), ud.Object, originalIdx, isNameIndex); - - if (v.IsVoid()) - { - throw ScriptRuntimeException.UserDataMissingField(ud.Descriptor.Name, idx.String); - } - - m_ValueStack.Push(v); - return instructionPtr; - } - else - { - h = GetMetamethodRaw(obj, "__index"); - - if (h.IsNil()) - throw ScriptRuntimeException.IndexType(obj); - } - - if (h.Type == DataType.Function || h.Type == DataType.ClrFunction) - { - if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index through metamethods. userdata expected"); - m_ValueStack.Push(h); - m_ValueStack.Push(obj); - m_ValueStack.Push(idx); - return Internal_ExecCall(false, 2, instructionPtr); - } - else - { - obj = h; - h = DynValue.Nil; - } - } - - throw ScriptRuntimeException.LoopInIndex(); - } - - - - - - } -} diff --git a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs b/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs deleted file mode 100644 index 880a8b58..00000000 --- a/src/MoonSharp.Interpreter/Execution/VM/Processor/Processor_UtilityFunctions.cs +++ /dev/null @@ -1,149 +0,0 @@ -using System.Collections.Generic; - -namespace MoonSharp.Interpreter.Execution.VM -{ - sealed partial class Processor - { - private DynValue[] Internal_AdjustTuple(IList values) - { - if (values == null || values.Count == 0) - return new DynValue[0]; - - if (values[values.Count - 1].Type == DataType.Tuple) - { - int baseLen = values.Count - 1 + values[values.Count - 1].Tuple.Length; - DynValue[] result = new DynValue[baseLen]; - - for (int i = 0; i < values.Count - 1; i++) - { - result[i] = values[i].ToScalar(); - } - - for (int i = 0; i < values[values.Count - 1].Tuple.Length; i++) - { - result[values.Count + i - 1] = values[values.Count - 1].Tuple[i]; - } - - if (result[result.Length - 1].Type == DataType.Tuple) - return Internal_AdjustTuple(result); - else - return result; - } - else - { - DynValue[] result = new DynValue[values.Count]; - - for (int i = 0; i < values.Count; i++) - { - result[i] = values[i].ToScalar(); - } - - return result; - } - } - - - - private int Internal_InvokeUnaryMetaMethod(DynValue op1, string eventName, int instructionPtr) - { - DynValue m = DynValue.Nil; - - if (op1.Type == DataType.UserData) - { - m = op1.UserData.Descriptor.MetaIndex(m_Script, op1.UserData.Object, eventName); - } - - if (m.IsNil()) - { - var op1_MetaTable = GetMetatable(op1); - - if (op1_MetaTable != null) - { - DynValue meta1 = op1_MetaTable.RawGet(eventName); - if (meta1.IsNotNil()) - m = meta1; - } - } - - if (m.IsNotNil()) - { - m_ValueStack.Push(m); - m_ValueStack.Push(op1); - return Internal_ExecCall(false, 1, instructionPtr); - } - else - { - return -1; - } - } - private int Internal_InvokeBinaryMetaMethod(DynValue l, DynValue r, string eventName, int instructionPtr, DynValue extraPush = default) - { - var m = GetBinaryMetamethod(l, r, eventName); - - if (m.IsNotNil()) - { - if (extraPush.IsNotNil()) - m_ValueStack.Push(extraPush); - - m_ValueStack.Push(m); - m_ValueStack.Push(l); - m_ValueStack.Push(r); - return Internal_ExecCall(false, 2, instructionPtr); - } - else - { - return -1; - } - } - - - - - private DynValue[] StackTopToArray(int items, bool pop) - { - DynValue[] values = new DynValue[items]; - - if (pop) - { - for (int i = 0; i < items; i++) - { - values[i] = m_ValueStack.Pop(); - } - } - else - { - for (int i = 0; i < items; i++) - { - values[i] = m_ValueStack[m_ValueStack.Count - 1 - i]; - } - } - - return values; - } - - private DynValue[] StackTopToArrayReverse(int items, bool pop) - { - DynValue[] values = new DynValue[items]; - - if (pop) - { - for (int i = 0; i < items; i++) - { - values[items - 1 - i] = m_ValueStack.Pop(); - } - } - else - { - for (int i = 0; i < items; i++) - { - values[items - 1 - i] = m_ValueStack[m_ValueStack.Count - 1 - i]; - } - } - - return values; - } - - - - } -} diff --git a/src/MoonSharp.Interpreter/Interop/Converters/ScriptToClrConversions.cs b/src/MoonSharp.Interpreter/Interop/Converters/ScriptToClrConversions.cs deleted file mode 100755 index 0cd0d3f3..00000000 --- a/src/MoonSharp.Interpreter/Interop/Converters/ScriptToClrConversions.cs +++ /dev/null @@ -1,320 +0,0 @@ -using System; - -namespace MoonSharp.Interpreter.Interop.Converters -{ - internal static class ScriptToClrConversions - { - internal const int WEIGHT_MAX_VALUE = 100; - internal const int WEIGHT_CUSTOM_CONVERTER_MATCH = 100; - internal const int WEIGHT_EXACT_MATCH = 100; - internal const int WEIGHT_STRING_TO_STRINGBUILDER = 99; - internal const int WEIGHT_STRING_TO_CHAR = 98; - internal const int WEIGHT_NIL_TO_NULLABLE = 100; - internal const int WEIGHT_NIL_TO_REFTYPE = 100; - internal const int WEIGHT_VOID_WITH_DEFAULT = 50; - internal const int WEIGHT_VOID_WITHOUT_DEFAULT = 25; - internal const int WEIGHT_NIL_WITH_DEFAULT = 25; - internal const int WEIGHT_BOOL_TO_STRING = 5; - internal const int WEIGHT_NUMBER_TO_STRING = 50; - internal const int WEIGHT_NUMBER_TO_ENUM = 90; - internal const int WEIGHT_USERDATA_TO_STRING = 5; - internal const int WEIGHT_TABLE_CONVERSION = 90; - internal const int WEIGHT_NUMBER_DOWNCAST = 99; - internal const int WEIGHT_NO_MATCH = 0; - internal const int WEIGHT_NO_EXTRA_PARAMS_BONUS = 100; - internal const int WEIGHT_EXTRA_PARAMS_MALUS = 2; - internal const int WEIGHT_BYREF_BONUSMALUS = -10; - internal const int WEIGHT_VARARGS_MALUS = 1; - internal const int WEIGHT_VARARGS_EMPTY = 40; - - /// - /// Converts a DynValue to a CLR object [simple conversion] - /// - internal static object DynValueToObject(DynValue value) - { - var converter = Script.GlobalOptions.CustomConverters.GetScriptToClrCustomConversion(value.Type, typeof(System.Object)); - if (converter != null) - { - var v = converter(value); - if (v != null) - return v; - } - - switch (value.Type) - { - case DataType.Void: - case DataType.Nil: - return null; - case DataType.Boolean: - return value.Boolean; - case DataType.Number: - return value.Number; - case DataType.String: - return value.String; - case DataType.Function: - return value.Function; - case DataType.Table: - return value.Table; - case DataType.Tuple: - return value.Tuple; - case DataType.UserData: - if (value.UserData.Object != null) - return value.UserData.Object; - else if (value.UserData.Descriptor != null) - return value.UserData.Descriptor.Type; - else - return null; - case DataType.ClrFunction: - return value.Callback; - default: - throw ScriptRuntimeException.ConvertObjectFailed(value.Type); - } - } - - - /// - /// Converts a DynValue to a CLR object of a specific type - /// - internal static object DynValueToObjectOfType(DynValue value, Type desiredType, object defaultValue, bool isOptional) - { - if (desiredType.IsByRef) - desiredType = desiredType.GetElementType(); - - var converter = Script.GlobalOptions.CustomConverters.GetScriptToClrCustomConversion(value.Type, desiredType); - if (converter != null) - { - var v = converter(value); - if (v != null) return v; - } - - if (desiredType == typeof(DynValue)) - return value; - - if (desiredType == typeof(object)) - return DynValueToObject(value); - - StringConversions.StringSubtype stringSubType = StringConversions.GetStringSubtype(desiredType); - string str = null; - - Type nt = Nullable.GetUnderlyingType(desiredType); - Type nullableType = null; - - if (nt != null) - { - nullableType = desiredType; - desiredType = nt; - } - - switch (value.Type) - { - case DataType.Void: - if (isOptional) - return defaultValue; - else if (!desiredType.IsValueType || (nullableType != null)) - return null; - break; - case DataType.Nil: - if (desiredType.IsValueType) - { - if (nullableType != null) - return null; - - if (isOptional) - return defaultValue; - } - else - { - return null; - } - break; - case DataType.Boolean: - if (desiredType == typeof(bool)) - return value.Boolean; - if (stringSubType != StringConversions.StringSubtype.None) - str = value.Boolean.ToString(); - break; - case DataType.Number: - if (desiredType.IsEnum) - { // number to enum conv - Type underType = Enum.GetUnderlyingType(desiredType); - return NumericConversions.DoubleToType(underType, value.Number); - } - if (NumericConversions.NumericTypes.Contains(desiredType)) - { - object d = NumericConversions.DoubleToType(desiredType, value.Number); - if (d.GetType() == desiredType) - return d; - break; - } - if (stringSubType != StringConversions.StringSubtype.None) - str = value.Number.ToString(); - break; - case DataType.String: - if (stringSubType != StringConversions.StringSubtype.None) - str = value.String; - break; - case DataType.Function: - if (desiredType == typeof(Closure)) return value.Function; - else if (desiredType == typeof(ScriptFunctionDelegate)) return value.Function.GetDelegate(); - break; - case DataType.ClrFunction: - if (desiredType == typeof(CallbackFunction)) return value.Callback; - else if (desiredType == typeof(Func)) return value.Callback.ClrCallback; - break; - case DataType.UserData: - if (value.UserData.Object != null) - { - var udObj = value.UserData.Object; - var udDesc = value.UserData.Descriptor; - - if (udDesc.IsTypeCompatible(desiredType, udObj)) - return udObj; - - if (stringSubType != StringConversions.StringSubtype.None) - str = udDesc.AsString(udObj); - } - break; - case DataType.Table: - if (desiredType == typeof(Table) || desiredType.IsAssignableFrom(typeof(Table))) - return value.Table; - else - { - object o = TableConversions.ConvertTableToType(value.Table, desiredType); - if (o != null) - return o; - } - break; - case DataType.Tuple: - break; - } - - if (stringSubType != StringConversions.StringSubtype.None && str != null) - return StringConversions.ConvertString(stringSubType, str, desiredType, value.Type); - - throw ScriptRuntimeException.ConvertObjectFailed(value.Type, desiredType); - } - - /// - /// Gets a relative weight of how much the conversion is matching the given types. - /// Implementation must follow that of DynValueToObjectOfType.. it's not very DRY in that sense. - /// However here we are in perf-sensitive path.. TODO : double-check the gain and see if a DRY impl is better. - /// - internal static int DynValueToObjectOfTypeWeight(DynValue value, Type desiredType, bool isOptional) - { - if (desiredType.IsByRef) - desiredType = desiredType.GetElementType(); - - var customConverter = Script.GlobalOptions.CustomConverters.GetScriptToClrCustomConversion(value.Type, desiredType); - if (customConverter != null) - return WEIGHT_CUSTOM_CONVERTER_MATCH; - - if (desiredType == typeof(DynValue)) - return WEIGHT_EXACT_MATCH; - - if (desiredType == typeof(object)) - return WEIGHT_EXACT_MATCH; - - StringConversions.StringSubtype stringSubType = StringConversions.GetStringSubtype(desiredType); - - Type nt = Nullable.GetUnderlyingType(desiredType); - Type nullableType = null; - - if (nt != null) - { - nullableType = desiredType; - desiredType = nt; - } - - switch (value.Type) - { - case DataType.Void: - if (isOptional) - return WEIGHT_VOID_WITH_DEFAULT; - else if (desiredType.IsValueType || (nullableType != null)) - return WEIGHT_VOID_WITHOUT_DEFAULT; - break; - case DataType.Nil: - if (desiredType.IsValueType) - { - if (nullableType != null) - return WEIGHT_NIL_TO_NULLABLE; - - if (isOptional) - return WEIGHT_NIL_WITH_DEFAULT; - } - else - { - return WEIGHT_NIL_TO_REFTYPE; - } - break; - case DataType.Boolean: - if (desiredType == typeof(bool)) - return WEIGHT_EXACT_MATCH; - if (stringSubType != StringConversions.StringSubtype.None) - return WEIGHT_BOOL_TO_STRING; - break; - case DataType.Number: - if (desiredType.IsEnum) - { // number to enum conv - return WEIGHT_NUMBER_TO_ENUM; - } - if (NumericConversions.NumericTypes.Contains(desiredType)) - return GetNumericTypeWeight(desiredType); - if (stringSubType != StringConversions.StringSubtype.None) - return WEIGHT_NUMBER_TO_STRING; - break; - case DataType.String: - if (stringSubType == StringConversions.StringSubtype.String) - return WEIGHT_EXACT_MATCH; - else if (stringSubType == StringConversions.StringSubtype.StringBuilder) - return WEIGHT_STRING_TO_STRINGBUILDER; - else if (stringSubType == StringConversions.StringSubtype.Char) - return WEIGHT_STRING_TO_CHAR; - break; - case DataType.Function: - if (desiredType == typeof(Closure)) return WEIGHT_EXACT_MATCH; - else if (desiredType == typeof(ScriptFunctionDelegate)) return WEIGHT_EXACT_MATCH; - break; - case DataType.ClrFunction: - if (desiredType == typeof(CallbackFunction)) return WEIGHT_EXACT_MATCH; - else if (desiredType == typeof(Func)) return WEIGHT_EXACT_MATCH; - break; - case DataType.UserData: - if (value.UserData.Object != null) - { - var udObj = value.UserData.Object; - var udDesc = value.UserData.Descriptor; - - if (udDesc.IsTypeCompatible(desiredType, udObj)) - return WEIGHT_EXACT_MATCH; - - if (stringSubType != StringConversions.StringSubtype.None) - return WEIGHT_USERDATA_TO_STRING; - } - break; - case DataType.Table: - if (desiredType == typeof(Table) || desiredType.IsAssignableFrom(typeof(Table))) - return WEIGHT_EXACT_MATCH; - else if (TableConversions.CanConvertTableToType(value.Table, desiredType)) - return WEIGHT_TABLE_CONVERSION; - break; - case DataType.Tuple: - break; - } - - return WEIGHT_NO_MATCH; - } - - private static int GetNumericTypeWeight(Type desiredType) - { - if (desiredType == typeof(double) || desiredType == typeof(decimal)) - return WEIGHT_EXACT_MATCH; - else - return WEIGHT_NUMBER_DOWNCAST; - } - - - - - } -} diff --git a/src/MoonSharp.Interpreter/Interop/IWireableDescriptor.cs b/src/MoonSharp.Interpreter/Interop/IWireableDescriptor.cs deleted file mode 100644 index 7bbe8996..00000000 --- a/src/MoonSharp.Interpreter/Interop/IWireableDescriptor.cs +++ /dev/null @@ -1,17 +0,0 @@ - -namespace MoonSharp.Interpreter.Interop.BasicDescriptors -{ - /// - /// Interface for descriptors with the capability of being serialized - /// for later hardwiring. - /// - public interface IWireableDescriptor - { - /// - /// Prepares the descriptor for hard-wiring. - /// The descriptor fills the passed table with all the needed data for hardwire generators to generate the appropriate code. - /// - /// The table to be filled - void PrepareForWiring(Table t); - } -} diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs deleted file mode 100644 index dc1b2c62..00000000 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/CharPtr.cs +++ /dev/null @@ -1,216 +0,0 @@ -#pragma warning disable 1591 -// -// This part taken from KopiLua - https://github.com/NLua/KopiLua -// -// ========================================================================================================= -// -// Kopi Lua License -// ---------------- -// MIT License for KopiLua -// Copyright (c) 2012 LoDC -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or substantial -// portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// =============================================================================== -// Lua License -// ----------- -// Lua is licensed under the terms of the MIT license reproduced below. -// This means that Lua is free software and can be used for both academic -// and commercial purposes at absolutely no cost. -// For details and rationale, see http://www.lua.org/license.html . -// =============================================================================== -// Copyright (C) 1994-2008 Lua.org, PUC-Rio. -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System; -using System.Diagnostics; - -namespace MoonSharp.Interpreter.Interop.LuaStateInterop -{ - public class CharPtr - { - public char[] chars; - public int index; - - public char this[int offset] - { - get { return chars[index + offset]; } - set { chars[index + offset] = value; } - } - - public char this[uint offset] - { - get { return chars[index + offset]; } - set { chars[index + offset] = value; } - } - public char this[long offset] - { - get { return chars[index + (int)offset]; } - set { chars[index + (int)offset] = value; } - } - - public static implicit operator CharPtr(string str) { return new CharPtr(str); } - public static implicit operator CharPtr(char[] chars) { return new CharPtr(chars); } - public static implicit operator CharPtr(byte[] bytes) { return new CharPtr(bytes); } - - public CharPtr() - { - this.chars = null; - this.index = 0; - } - - public CharPtr(string str) - { - this.chars = (str + '\0').ToCharArray(); - this.index = 0; - } - - public CharPtr(CharPtr ptr) - { - this.chars = ptr.chars; - this.index = ptr.index; - } - - public CharPtr(CharPtr ptr, int index) - { - this.chars = ptr.chars; - this.index = index; - } - - public CharPtr(char[] chars) - { - this.chars = chars; - this.index = 0; - } - - public CharPtr(char[] chars, int index) - { - this.chars = chars; - this.index = index; - } - - public CharPtr(byte[] bytes) - { - this.chars = new char[bytes.Length]; - for (int i = 0; i < bytes.Length; i++) - { - this.chars[i] = (char)bytes[i]; - } - - this.index = 0; - } - - public CharPtr(IntPtr ptr) - { - this.chars = new char[0]; - this.index = 0; - } - - public static CharPtr operator +(CharPtr ptr, int offset) { return new CharPtr(ptr.chars, ptr.index + offset); } - public static CharPtr operator -(CharPtr ptr, int offset) { return new CharPtr(ptr.chars, ptr.index - offset); } - public static CharPtr operator +(CharPtr ptr, uint offset) { return new CharPtr(ptr.chars, ptr.index + (int)offset); } - public static CharPtr operator -(CharPtr ptr, uint offset) { return new CharPtr(ptr.chars, ptr.index - (int)offset); } - - public void inc() { this.index++; } - public void dec() { this.index--; } - public CharPtr next() { return new CharPtr(this.chars, this.index + 1); } - public CharPtr prev() { return new CharPtr(this.chars, this.index - 1); } - public CharPtr add(int ofs) { return new CharPtr(this.chars, this.index + ofs); } - public CharPtr sub(int ofs) { return new CharPtr(this.chars, this.index - ofs); } - - public static bool operator ==(CharPtr ptr, char ch) { return ptr[0] == ch; } - public static bool operator ==(char ch, CharPtr ptr) { return ptr[0] == ch; } - public static bool operator !=(CharPtr ptr, char ch) { return ptr[0] != ch; } - public static bool operator !=(char ch, CharPtr ptr) { return ptr[0] != ch; } - - public static CharPtr operator +(CharPtr ptr1, CharPtr ptr2) - { - string result = ""; - for (int i = 0; ptr1[i] != '\0'; i++) - result += ptr1[i]; - for (int i = 0; ptr2[i] != '\0'; i++) - result += ptr2[i]; - return new CharPtr(result); - } - public static int operator -(CharPtr ptr1, CharPtr ptr2) - { - Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index - ptr2.index; - } - public static bool operator <(CharPtr ptr1, CharPtr ptr2) - { - Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index < ptr2.index; - } - public static bool operator <=(CharPtr ptr1, CharPtr ptr2) - { - Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index <= ptr2.index; - } - public static bool operator >(CharPtr ptr1, CharPtr ptr2) - { - Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index > ptr2.index; - } - public static bool operator >=(CharPtr ptr1, CharPtr ptr2) - { - Debug.Assert(ptr1.chars == ptr2.chars); return ptr1.index >= ptr2.index; - } - public static bool operator ==(CharPtr ptr1, CharPtr ptr2) - { - object o1 = ptr1 as CharPtr; - object o2 = ptr2 as CharPtr; - if ((o1 == null) && (o2 == null)) return true; - if (o1 == null) return false; - if (o2 == null) return false; - return (ptr1.chars == ptr2.chars) && (ptr1.index == ptr2.index); - } - public static bool operator !=(CharPtr ptr1, CharPtr ptr2) { return !(ptr1 == ptr2); } - - public override bool Equals(object o) - { - return this == (o as CharPtr); - } - - public override int GetHashCode() - { - return 0; - } - public override string ToString() - { - System.Text.StringBuilder result = new System.Text.StringBuilder(); - for (int i = index; (i < chars.Length) && (chars[i] != '\0'); i++) - result.Append(chars[i]); - - return result.ToString(); - } - - public string ToString(int length) - { - System.Text.StringBuilder result = new System.Text.StringBuilder(); - for (int i = index; (i < chars.Length) && i < (length + index); i++) - result.Append(chars[i]); - return result.ToString(); - } - } - -} diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs deleted file mode 100644 index 1bc2bb2a..00000000 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase.cs +++ /dev/null @@ -1,323 +0,0 @@ -// Disable warnings about XML documentation -#pragma warning disable 1591 - -using System; -using lua_Integer = System.Int32; - -namespace MoonSharp.Interpreter.Interop.LuaStateInterop -{ - /// - /// Classes using the classic interface should inherit from this class. - /// This class defines only static methods and is really meant to be used only - /// from C# and not other .NET languages. - /// - /// For easier operation they should also define: - /// using ptrdiff_t = System.Int32; - /// using lua_Integer = System.Int32; - /// using LUA_INTFRM_T = System.Int64; - /// using UNSIGNED_LUA_INTFRM_T = System.UInt64; - /// - public partial class LuaBase - { - protected const int LUA_TNONE = -1; - protected const int LUA_TNIL = 0; - protected const int LUA_TBOOLEAN = 1; - protected const int LUA_TLIGHTUSERDATA = 2; - protected const int LUA_TNUMBER = 3; - protected const int LUA_TSTRING = 4; - protected const int LUA_TTABLE = 5; - protected const int LUA_TFUNCTION = 6; - protected const int LUA_TUSERDATA = 7; - protected const int LUA_TTHREAD = 8; - - protected const int LUA_MULTRET = -1; - - protected const string LUA_INTFRMLEN = "l"; - - protected static DynValue GetArgument(LuaState L, lua_Integer pos) - { - return L.At(pos); - } - - protected static DynValue ArgAsType(LuaState L, lua_Integer pos, DataType type, bool allowNil = false) - { - return GetArgument(L, pos).CheckType(L.FunctionName, type, pos - 1, allowNil ? TypeValidationFlags.AllowNil | TypeValidationFlags.AutoConvert : TypeValidationFlags.AutoConvert); - } - - protected static lua_Integer LuaType(LuaState L, lua_Integer p) - { - switch (GetArgument(L, p).Type) - { - case DataType.Void: - return LUA_TNONE; - case DataType.Nil: - return LUA_TNIL; - case DataType.Boolean: - return LUA_TNIL; - case DataType.Number: - return LUA_TNUMBER; - case DataType.String: - return LUA_TSTRING; - case DataType.Function: - return LUA_TFUNCTION; - case DataType.Table: - return LUA_TTABLE; - case DataType.UserData: - return LUA_TUSERDATA; - case DataType.Thread: - return LUA_TTHREAD; - case DataType.ClrFunction: - return LUA_TFUNCTION; - case DataType.TailCallRequest: - case DataType.YieldRequest: - case DataType.Tuple: - default: - throw new ScriptRuntimeException("Can't call LuaType on any type"); - } - } - - protected static string LuaLCheckLString(LuaState L, lua_Integer argNum, out uint l, bool allowNil = false) - { - string str = ArgAsType(L, argNum, DataType.String, allowNil).String; - l = (uint)(str?.Length ?? 0); - return str; - } - - protected static void LuaPushInteger(LuaState L, lua_Integer val) - { - L.Push(DynValue.NewNumber(val)); - } - - protected static lua_Integer LuaToBoolean(LuaState L, lua_Integer p) - { - return GetArgument(L, p).CastToBool() ? 1 : 0; - } - - protected static string LuaToLString(LuaState luaState, lua_Integer p, out uint l) - { - return LuaLCheckLString(luaState, p, out l); - } - - protected static string LuaToString(LuaState luaState, lua_Integer p) - { - uint l; - return LuaLCheckLString(luaState, p, out l); - } - - protected static void LuaLAddValue(LuaLBuffer b) - { - b.StringBuilder.Append(b.LuaState.Pop().ToPrintString()); - } - - protected static void LuaLAddLString(LuaLBuffer b, CharPtr s, uint p) - { - b.StringBuilder.Append(s.ToString((int)p)); - } - - protected static void LuaLAddString(LuaLBuffer b, string s) - { - b.StringBuilder.Append(s.ToString()); - } - - - protected static lua_Integer LuaLOptInteger(LuaState L, lua_Integer pos, lua_Integer def) - { - DynValue v = ArgAsType(L, pos, DataType.Number, true); - - if (v.IsNil()) - return def; - else - return (int)v.Number; - } - - protected static lua_Integer LuaLCheckInteger(LuaState L, lua_Integer pos) - { - DynValue v = ArgAsType(L, pos, DataType.Number, false); - return (int)v.Number; - } - - protected static void LuaLArgCheck(LuaState L, bool condition, lua_Integer argNum, string message) - { - if (!condition) - LuaLArgError(L, argNum, message); - } - - protected static lua_Integer LuaLCheckInt(LuaState L, lua_Integer argNum) - { - return LuaLCheckInteger(L, argNum); - } - - protected static lua_Integer LuaGetTop(LuaState L) - { - return L.Count; - } - - protected static lua_Integer LuaLError(LuaState luaState, string message, params object[] args) - { - throw new ScriptRuntimeException(message, args); - } - - protected static void LuaLAddChar(LuaLBuffer b, char p) - { - b.StringBuilder.Append(p); - } - - protected static void LuaLBuffInit(LuaState L, LuaLBuffer b) - { - } - - protected static void LuaPushLiteral(LuaState L, string literalString) - { - L.Push(DynValue.NewString(literalString)); - } - - protected static void LuaLPushResult(LuaLBuffer b) - { - LuaPushLiteral(b.LuaState, b.StringBuilder.ToString()); - } - - protected static void LuaPushLString(LuaState L, CharPtr s, uint len) - { - string ss = s.ToString((int)len); - L.Push(DynValue.NewString(ss)); - } - - protected static void LuaLCheckStack(LuaState L, lua_Integer n, string message) - { - // nop ? - } - - protected static string LUA_QL(string p) - { - return "'" + p + "'"; - } - - - protected static void LuaPushNil(LuaState L) - { - L.Push(DynValue.Nil); - } - - protected static void LuaAssert(bool p) - { - // ??! - // A lot of KopiLua methods fall here in valid state! - - //if (!p) - // throw new InternalErrorException("LuaAssert failed!"); - } - - protected static string LuaLTypeName(LuaState L, lua_Integer p) - { - return L.At(p).Type.ToErrorTypeString(); - } - - protected static lua_Integer LuaIsString(LuaState L, lua_Integer p) - { - var v = L.At(p); - return (v.Type == DataType.String || v.Type == DataType.Number) ? 1 : 0; - } - - protected static void LuaPop(LuaState L, lua_Integer p) - { - for (int i = 0; i < p; i++) - L.Pop(); - } - - protected static void LuaGetTable(LuaState L, lua_Integer p) - { - // DEBT: this should call metamethods, now it performs raw access - DynValue key = L.Pop(); - DynValue table = L.At(p); - - if (table.Type != DataType.Table) - throw new NotImplementedException(); - - var v = table.Table.Get(key); - L.Push(v); - } - - protected static int LuaLOptInt(LuaState L, lua_Integer pos, lua_Integer def) - { - return LuaLOptInteger(L, pos, def); - } - - protected static CharPtr LuaLCheckString(LuaState L, lua_Integer p) - { - uint dummy; - return LuaLCheckLString(L, p, out dummy); - } - - protected static string LuaLCheckStringStr(LuaState L, lua_Integer p) - { - uint dummy; - return LuaLCheckLString(L, p, out dummy); - } - - protected static void LuaLArgError(LuaState L, lua_Integer arg, string p) - { - throw ScriptRuntimeException.BadArgument(arg - 1, L.FunctionName, p); - } - - protected static double LuaLCheckNumber(LuaState L, lua_Integer pos) - { - DynValue v = ArgAsType(L, pos, DataType.Number, false); - return v.Number; - } - - protected static void LuaPushValue(LuaState L, lua_Integer arg) - { - DynValue v = L.At(arg); - L.Push(v); - } - - - /// - /// Calls a function. - /// To call a function you must use the following protocol: first, the function to be called is pushed onto the stack; then, - /// the arguments to the function are pushed in direct order; that is, the first argument is pushed first. Finally you call - /// lua_call; nargs is the number of arguments that you pushed onto the stack. All arguments and the function value are - /// popped from the stack when the function is called. The function results are pushed onto the stack when the function - /// returns. The number of results is adjusted to nresults, unless nresults is LUA_MULTRET. In this case, all results from - /// the function are pushed. Lua takes care that the returned values fit into the stack space. The function results are - /// pushed onto the stack in direct order (the first result is pushed first), so that after the call the last result is on - /// the top of the stack. - /// - /// The LuaState - /// The number of arguments. - /// The number of expected results. - /// - protected static void LuaCall(LuaState L, lua_Integer nargs, lua_Integer nresults = LUA_MULTRET) - { - DynValue[] args = L.GetTopArray(nargs); - - L.Discard(nargs); - - DynValue func = L.Pop(); - - DynValue ret = L.ExecutionContext.Call(func, args); - - if (nresults != 0) - { - if (nresults == -1) - { - nresults = (ret.Type == DataType.Tuple) ? ret.Tuple.Length : 1; - } - - DynValue[] vals = (ret.Type == DataType.Tuple) ? ret.Tuple : new DynValue[1] { ret }; - - int copied = 0; - - for (int i = 0; i < vals.Length && copied < nresults; i++, copied++) - { - L.Push(vals[i]); - } - - while (copied < nresults) - { - L.Push(DynValue.Nil); - } - } - } - } -} diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase_CLib.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase_CLib.cs deleted file mode 100644 index b5ebfc2f..00000000 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaBase_CLib.cs +++ /dev/null @@ -1,119 +0,0 @@ -// Disable warnings about XML documentation -#pragma warning disable 1591 - -using System; -using lua_Integer = System.Int32; - -namespace MoonSharp.Interpreter.Interop.LuaStateInterop -{ - public partial class LuaBase - { - protected static lua_Integer memcmp(CharPtr ptr1, CharPtr ptr2, uint size) - { - return memcmp(ptr1, ptr2, (int)size); - } - - protected static int memcmp(CharPtr ptr1, CharPtr ptr2, int size) - { - for (int i = 0; i < size; i++) - if (ptr1[i] != ptr2[i]) - { - if (ptr1[i] < ptr2[i]) - return -1; - else - return 1; - } - return 0; - } - - protected static CharPtr memchr(CharPtr ptr, char c, uint count) - { - for (uint i = 0; i < count; i++) - if (ptr[i] == c) - return new CharPtr(ptr.chars, (int)(ptr.index + i)); - return null; - } - - protected static CharPtr strpbrk(CharPtr str, CharPtr charset) - { - for (int i = 0; str[i] != '\0'; i++) - for (int j = 0; charset[j] != '\0'; j++) - if (str[i] == charset[j]) - return new CharPtr(str.chars, str.index + i); - return null; - } - - protected static bool isalpha(char c) { return Char.IsLetter(c); } - protected static bool iscntrl(char c) { return Char.IsControl(c); } - protected static bool isdigit(char c) { return Char.IsDigit(c); } - protected static bool islower(char c) { return Char.IsLower(c); } - protected static bool ispunct(char c) { return Char.IsPunctuation(c); } - protected static bool isspace(char c) { return (c == ' ') || (c >= (char)0x09 && c <= (char)0x0D); } - protected static bool isupper(char c) { return Char.IsUpper(c); } - protected static bool isalnum(char c) { return Char.IsLetterOrDigit(c); } - protected static bool isxdigit(char c) { return "0123456789ABCDEFabcdef".IndexOf(c) >= 0; } - protected static bool isgraph(char c) { return !Char.IsControl(c) && !Char.IsWhiteSpace(c); } - - protected static bool isalpha(int c) { return Char.IsLetter((char)c); } - protected static bool iscntrl(int c) { return Char.IsControl((char)c); } - protected static bool isdigit(int c) { return Char.IsDigit((char)c); } - protected static bool islower(int c) { return Char.IsLower((char)c); } - protected static bool ispunct(int c) { return ((char)c != ' ') && !isalnum((char)c); } // *not* the same as Char.IsPunctuation - protected static bool isspace(int c) { return ((char)c == ' ') || ((char)c >= (char)0x09 && (char)c <= (char)0x0D); } - protected static bool isupper(int c) { return Char.IsUpper((char)c); } - protected static bool isalnum(int c) { return Char.IsLetterOrDigit((char)c); } - protected static bool isgraph(int c) { return !Char.IsControl((char)c) && !Char.IsWhiteSpace((char)c); } - - protected static char tolower(char c) { return Char.ToLower(c); } - protected static char toupper(char c) { return Char.ToUpper(c); } - protected static char tolower(int c) { return Char.ToLower((char)c); } - protected static char toupper(int c) { return Char.ToUpper((char)c); } - - - // find c in str - protected static CharPtr strchr(CharPtr str, char c) - { - for (int index = str.index; str.chars[index] != 0; index++) - if (str.chars[index] == c) - return new CharPtr(str.chars, index); - return null; - } - - protected static CharPtr strcpy(CharPtr dst, CharPtr src) - { - int i; - for (i = 0; src[i] != '\0'; i++) - dst[i] = src[i]; - dst[i] = '\0'; - return dst; - } - - protected static CharPtr strncpy(CharPtr dst, CharPtr src, int length) - { - int index = 0; - while ((src[index] != '\0') && (index < length)) - { - dst[index] = src[index]; - index++; - } - while (index < length) - dst[index++] = '\0'; - return dst; - } - - protected static int strlen(CharPtr str) - { - int index = 0; - while (str[index] != '\0') - index++; - return index; - } - - public static void sprintf(CharPtr buffer, CharPtr str, params object[] argv) - { - string temp = Tools.sprintf(str.ToString(), argv); - strcpy(buffer, temp); - } - - } -} diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaLBuffer.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaLBuffer.cs deleted file mode 100644 index ed3ba873..00000000 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaLBuffer.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Disable warnings about XML documentation -#pragma warning disable 1591 - -using System.Text; - -namespace MoonSharp.Interpreter.Interop.LuaStateInterop -{ - public class LuaLBuffer - { - public StringBuilder StringBuilder { get; private set; } - public LuaState LuaState { get; private set; } - - public LuaLBuffer(LuaState l) - { - StringBuilder = new StringBuilder(); - LuaState = l; - } - - - } -} diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs deleted file mode 100644 index 94fbbbcb..00000000 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/LuaState.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Disable warnings about XML documentation -#pragma warning disable 1591 - -using System.Collections.Generic; - -namespace MoonSharp.Interpreter.Interop.LuaStateInterop -{ - /// - /// - /// - public class LuaState - { - private List m_Stack; - - public ScriptExecutionContext ExecutionContext { get; private set; } - public string FunctionName { get; private set; } - - internal LuaState(ScriptExecutionContext executionContext, CallbackArguments args, string functionName) - { - ExecutionContext = executionContext; - m_Stack = new List(16); - - for (int i = 0; i < args.Count; i++) - m_Stack.Add(args[i]); - - FunctionName = functionName; - } - - public DynValue Top(int pos = 0) - { - return m_Stack[m_Stack.Count - 1 - pos]; - } - - public DynValue At(int pos) - { - if (pos < 0) - pos = m_Stack.Count + pos + 1; - - if (pos > m_Stack.Count) - return DynValue.Void; - - return m_Stack[pos - 1]; - } - - public int Count - { - get { return m_Stack.Count; } - } - - public void Push(DynValue v) - { - m_Stack.Add(v); - } - - public DynValue Pop() - { - var v = Top(); - m_Stack.RemoveAt(m_Stack.Count - 1); - return v; - } - - public DynValue[] GetTopArray(int num) - { - DynValue[] rets = new DynValue[num]; - - for (int i = 0; i < num; i++) - rets[num - i - 1] = Top(i); - - return rets; - } - - - public DynValue GetReturnValue(int retvals) - { - if (retvals == 0) - return DynValue.Nil; - else if (retvals == 1) - return Top(); - else - { - DynValue[] rets = GetTopArray(retvals); - return DynValue.NewTupleNested(rets); - } - } - - - - public void Discard(int nargs) - { - for(int i = 0; i < nargs; i++) - m_Stack.RemoveAt(m_Stack.Count - 1); - } - } -} diff --git a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/Tools.cs b/src/MoonSharp.Interpreter/Interop/LuaStateInterop/Tools.cs deleted file mode 100755 index 2bef6ad4..00000000 --- a/src/MoonSharp.Interpreter/Interop/LuaStateInterop/Tools.cs +++ /dev/null @@ -1,728 +0,0 @@ -// -// This part taken from KopiLua - https://github.com/NLua/KopiLua -// -// ========================================================================================================= -// -// Kopi Lua License -// ---------------- -// MIT License for KopiLua -// Copyright (c) 2012 LoDC -// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and -// associated documentation files (the "Software"), to deal in the Software without restriction, -// including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// The above copyright notice and this permission notice shall be included in all copies or substantial -// portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT -// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// =============================================================================== -// Lua License -// ----------- -// Lua is licensed under the terms of the MIT license reproduced below. -// This means that Lua is free software and can be used for both academic -// and commercial purposes at absolutely no cost. -// For details and rationale, see http://www.lua.org/license.html . -// =============================================================================== -// Copyright (C) 1994-2008 Lua.org, PUC-Rio. -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - - -#region Usings -using System; -using System.Globalization; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; - - -#endregion - -namespace MoonSharp.Interpreter.Interop.LuaStateInterop -{ - internal static class Tools - { - #region Public Methods - #region IsNumericType - /// - /// Determines whether the specified value is of numeric type. - /// - /// The object to check. - /// - /// true if o is a numeric type; otherwise, false. - /// - public static bool IsNumericType(object o) - { - return (o is byte || - o is sbyte || - o is short || - o is ushort || - o is int || - o is uint || - o is long || - o is ulong || - o is float || - o is double || - o is decimal); - } - #endregion - #region IsPositive - /// - /// Determines whether the specified value is positive. - /// - /// The value. - /// if set to true treats 0 as positive. - /// - /// true if the specified value is positive; otherwise, false. - /// - public static bool IsPositive(object Value, bool ZeroIsPositive) - { - Type t = Value.GetType(); - - if (t == typeof(sbyte)) - return (ZeroIsPositive ? (sbyte)Value >= 0 : (sbyte)Value > 0); - if (t == typeof(short)) - return (ZeroIsPositive ? (short)Value >= 0 : (short)Value > 0); - if (t == typeof(int)) - return (ZeroIsPositive ? (int)Value >= 0 : (int)Value > 0); - if (t == typeof(long)) - return (ZeroIsPositive ? (long)Value >= 0 : (long)Value > 0); - if (t == typeof(byte)) - return (ZeroIsPositive ? true : (byte)Value > 0); - if (t == typeof(ushort)) - return (ZeroIsPositive ? true : (ushort)Value > 0); - if (t == typeof(uint)) - return (ZeroIsPositive ? true : (uint)Value > 0); - if (t == typeof(ulong)) - return (ZeroIsPositive ? true : (ulong)Value > 0); - if (t == typeof(float)) - return (ZeroIsPositive ? (float)Value >= 0 : (float)Value > 0); - if (t == typeof(double)) - return (ZeroIsPositive ? (double)Value >= 0 : (double)Value > 0); - if (t == typeof(decimal)) - return (ZeroIsPositive ? (decimal)Value >= 0 : (decimal)Value > 0); - if (t == typeof(char)) - return (ZeroIsPositive ? true : (char)Value != '\0'); - - return ZeroIsPositive; - } - #endregion - #region ToUnsigned - /// - /// Converts the specified values boxed type to its correpsonding unsigned - /// type. - /// - /// The value. - /// A boxed numeric object whos type is unsigned. - public static object ToUnsigned(object Value) - { - Type t = Value.GetType(); - - if (t == typeof(sbyte)) - return (byte)((sbyte)Value); - if (t == typeof(short)) - return (ushort)((short)Value); - if (t == typeof(int)) - return (uint)((int)Value); - if (t == typeof(long)) - return (ulong)((long)Value); - if (t == typeof(byte)) - return Value; - if (t == typeof(ushort)) - return Value; - if (t == typeof(uint)) - return Value; - if (t == typeof(ulong)) - return Value; - if (t == typeof(float)) - return (uint)((float)Value); - if (t == typeof(double)) - return (ulong)((double)Value); - if (t == typeof(decimal)) - return (ulong)((decimal)Value); - - return null; - } - #endregion - #region ToInteger - /// - /// Converts the specified values boxed type to its correpsonding integer - /// type. - /// - /// The value. - /// if set to true [round]. - /// - /// A boxed numeric object whos type is an integer type. - /// - public static object ToInteger(object Value, bool Round) - { - Type t = Value.GetType(); - - if (t == typeof(sbyte)) - return Value; - if (t == typeof(short)) - return Value; - if (t == typeof(int)) - return Value; - if (t == typeof(long)) - return Value; - if (t == typeof(byte)) - return Value; - if (t == typeof(ushort)) - return Value; - if (t == typeof(uint)) - return Value; - if (t == typeof(ulong)) - return Value; - if (t == typeof(float)) - return (Round ? (int)Math.Round((float)Value) : (int)((float)Value)); - if (t == typeof(double)) - return (Round ? (long)Math.Round((double)Value) : (long)((double)Value)); - if (t == typeof(decimal)) - return (Round ? Math.Round((decimal)Value) : (decimal)Value); - - return null; - } - #endregion - #region UnboxToLong - public static long UnboxToLong(object Value, bool Round) - { - Type t = Value.GetType(); - - if (t == typeof(sbyte)) - return (long)((sbyte)Value); - if (t == typeof(short)) - return (long)((short)Value); - if (t == typeof(int)) - return (long)((int)Value); - if (t == typeof(long)) - return (long)Value; - if (t == typeof(byte)) - return (long)((byte)Value); - if (t == typeof(ushort)) - return (long)((ushort)Value); - if (t == typeof(uint)) - return (long)((uint)Value); - if (t == typeof(ulong)) - return (long)((ulong)Value); - if (t == typeof(float)) - return (Round ? (long)Math.Round((float)Value) : (long)((float)Value)); - if (t == typeof(double)) - return (Round ? (long)Math.Round((double)Value) : (long)((double)Value)); - if (t == typeof(decimal)) - return (Round ? (long)Math.Round((decimal)Value) : (long)((decimal)Value)); - - return 0; - } - #endregion - #region ReplaceMetaChars - /// - /// Replaces the string representations of meta chars with their corresponding - /// character values. - /// - /// The input. - /// A string with all string meta chars are replaced - public static string ReplaceMetaChars(string input) - { - return Regex.Replace(input, @"(\\)(\d{3}|[^\d])?", new MatchEvaluator(ReplaceMetaCharsMatch)); - } - private static string ReplaceMetaCharsMatch(Match m) - { - // convert octal quotes (like \040) - if (m.Groups[2].Length == 3) - return Convert.ToChar(Convert.ToByte(m.Groups[2].Value, 8)).ToString(); - else - { - // convert all other special meta characters - //TODO: \xhhh hex and possible dec !! - switch (m.Groups[2].Value) - { - case "0": // null - return "\0"; - case "a": // alert (beep) - return "\a"; - case "b": // BS - return "\b"; - case "f": // FF - return "\f"; - case "v": // vertical tab - return "\v"; - case "r": // CR - return "\r"; - case "n": // LF - return "\n"; - case "t": // Tab - return "\t"; - default: - // if neither an octal quote nor a special meta character - // so just remove the backslash - return m.Groups[2].Value; - } - } - } - #endregion - #region fprintf - public static void fprintf(TextWriter Destination, string Format, params object[] Parameters) - { - Destination.Write(Tools.sprintf(Format, Parameters)); - } - - - #endregion - #region sprintf - internal static Regex r = new Regex(@"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])"); - public static string sprintf(string Format, params object[] Parameters) - { - #region Variables - StringBuilder f = new StringBuilder(); - //Regex r = new Regex( @"\%(\d*\$)?([\'\#\-\+ ]*)(\d*)(?:\.(\d+))?([hl])?([dioxXucsfeEgGpn%])" ); - //"%[parameter][flags][width][.precision][length]type" - Match m = null; - string w = String.Empty; - int defaultParamIx = 0; - int paramIx; - object o = null; - - bool flagLeft2Right = false; - bool flagAlternate = false; - bool flagPositiveSign = false; - bool flagPositiveSpace = false; - bool flagZeroPadding = false; - bool flagGroupThousands = false; - - int fieldLength = 0; - int fieldPrecision = 0; - char shortLongIndicator = '\0'; - char formatSpecifier = '\0'; - char paddingCharacter = ' '; - #endregion - - // find all format parameters in format string - f.Append(Format); - m = r.Match(f.ToString()); - while (m.Success) - { - #region parameter index - paramIx = defaultParamIx; - if (m.Groups[1] != null && m.Groups[1].Value.Length > 0) - { - string val = m.Groups[1].Value.Substring(0, m.Groups[1].Value.Length - 1); - paramIx = Convert.ToInt32(val) - 1; - }; - #endregion - - #region format flags - // extract format flags - flagAlternate = false; - flagLeft2Right = false; - flagPositiveSign = false; - flagPositiveSpace = false; - flagZeroPadding = false; - flagGroupThousands = false; - if (m.Groups[2] != null && m.Groups[2].Value.Length > 0) - { - string flags = m.Groups[2].Value; - - flagAlternate = (flags.IndexOf('#') >= 0); - flagLeft2Right = (flags.IndexOf('-') >= 0); - flagPositiveSign = (flags.IndexOf('+') >= 0); - flagPositiveSpace = (flags.IndexOf(' ') >= 0); - flagGroupThousands = (flags.IndexOf('\'') >= 0); - - // positive + indicator overrides a - // positive space character - if (flagPositiveSign && flagPositiveSpace) - flagPositiveSpace = false; - } - #endregion - - #region field length - // extract field length and - // pading character - paddingCharacter = ' '; - fieldLength = int.MinValue; - if (m.Groups[3] != null && m.Groups[3].Value.Length > 0) - { - fieldLength = Convert.ToInt32(m.Groups[3].Value); - flagZeroPadding = (m.Groups[3].Value[0] == '0'); - } - #endregion - - if (flagZeroPadding) - paddingCharacter = '0'; - - // left2right allignment overrides zero padding - if (flagLeft2Right && flagZeroPadding) - { - flagZeroPadding = false; - paddingCharacter = ' '; - } - - #region field precision - // extract field precision - fieldPrecision = int.MinValue; - if (m.Groups[4] != null && m.Groups[4].Value.Length > 0) - fieldPrecision = Convert.ToInt32(m.Groups[4].Value); - #endregion - - #region short / long indicator - // extract short / long indicator - shortLongIndicator = Char.MinValue; - if (m.Groups[5] != null && m.Groups[5].Value.Length > 0) - shortLongIndicator = m.Groups[5].Value[0]; - #endregion - - #region format specifier - // extract format - formatSpecifier = Char.MinValue; - if (m.Groups[6] != null && m.Groups[6].Value.Length > 0) - formatSpecifier = m.Groups[6].Value[0]; - #endregion - - // default precision is 6 digits if none is specified except - if (fieldPrecision == int.MinValue && - formatSpecifier != 's' && - formatSpecifier != 'c' && - Char.ToUpper(formatSpecifier) != 'X' && - formatSpecifier != 'o') - fieldPrecision = 6; - - #region get next value parameter - // get next value parameter and convert value parameter depending on short / long indicator - if (Parameters == null || paramIx >= Parameters.Length) - o = null; - else - { - o = Parameters[paramIx]; - - if (shortLongIndicator == 'h') - { - if (o is int) - o = (short)((int)o); - else if (o is long) - o = (short)((long)o); - else if (o is uint) - o = (ushort)((uint)o); - else if (o is ulong) - o = (ushort)((ulong)o); - } - else if (shortLongIndicator == 'l') - { - if (o is short) - o = (long)((short)o); - else if (o is int) - o = (long)((int)o); - else if (o is ushort) - o = (ulong)((ushort)o); - else if (o is uint) - o = (ulong)((uint)o); - } - } - #endregion - - // convert value parameters to a string depending on the formatSpecifier - w = String.Empty; - switch (formatSpecifier) - { - #region % - character - case '%': // % character - w = "%"; - break; - #endregion - #region d - integer - case 'd': // integer - w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate, - fieldLength, int.MinValue, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region i - integer - case 'i': // integer - goto case 'd'; - #endregion - #region o - octal integer - case 'o': // octal integer - no leading zero - w = FormatOct("o", flagAlternate, - fieldLength, int.MinValue, flagLeft2Right, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region x - hex integer - case 'x': // hex integer - no leading zero - w = FormatHex("x", flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region X - hex integer - case 'X': // same as x but with capital hex characters - w = FormatHex("X", flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region u - unsigned integer - case 'u': // unsigned integer - w = FormatNumber((flagGroupThousands ? "n" : "d"), flagAlternate, - fieldLength, int.MinValue, flagLeft2Right, - false, false, - paddingCharacter, ToUnsigned(o)); - defaultParamIx++; - break; - #endregion - #region c - character - case 'c': // character - if (IsNumericType(o)) - w = Convert.ToChar(o).ToString(); - else if (o is char) - w = ((char)o).ToString(); - else if (o is string && ((string)o).Length > 0) - w = ((string)o)[0].ToString(); - defaultParamIx++; - break; - #endregion - #region s - string - case 's': // string - //string t = "{0" + ( fieldLength != int.MinValue ? "," + ( flagLeft2Right ? "-" : String.Empty ) + fieldLength.ToString() : String.Empty ) + ":s}"; - w = o.ToString(); - if (fieldPrecision >= 0) - w = w.Substring(0, fieldPrecision); - - if (fieldLength != int.MinValue) - if (flagLeft2Right) - w = w.PadRight(fieldLength, paddingCharacter); - else - w = w.PadLeft(fieldLength, paddingCharacter); - defaultParamIx++; - break; - #endregion - #region f - double number - case 'f': // double - w = FormatNumber((flagGroupThousands ? "n" : "f"), flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region e - exponent number - case 'e': // double / exponent - w = FormatNumber("e", flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region E - exponent number - case 'E': // double / exponent - w = FormatNumber("E", flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region g - general number - case 'g': // double / exponent - w = FormatNumber("g", flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region G - general number - case 'G': // double / exponent - w = FormatNumber("G", flagAlternate, - fieldLength, fieldPrecision, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, o); - defaultParamIx++; - break; - #endregion - #region p - pointer - case 'p': // pointer - if (o is IntPtr) - w = "0x" + ((IntPtr)o).ToString("x"); - defaultParamIx++; - break; - #endregion - #region n - number of processed chars so far - case 'n': // number of characters so far - w = FormatNumber("d", flagAlternate, - fieldLength, int.MinValue, flagLeft2Right, - flagPositiveSign, flagPositiveSpace, - paddingCharacter, m.Index); - break; - #endregion - default: - w = String.Empty; - defaultParamIx++; - break; - } - - // replace format parameter with parameter value - // and start searching for the next format parameter - // AFTER the position of the current inserted value - // to prohibit recursive matches if the value also - // includes a format specifier - f.Remove(m.Index, m.Length); - f.Insert(m.Index, w); - m = r.Match(f.ToString(), m.Index + w.Length); - } - - return f.ToString(); - } - #endregion - #endregion - - #region Private Methods - #region FormatOCT - private static string FormatOct(string NativeFormat, bool Alternate, - int FieldLength, int FieldPrecision, - bool Left2Right, - char Padding, object Value) - { - string w = String.Empty; - string lengthFormat = "{0" + (FieldLength != int.MinValue ? - "," + (Left2Right ? - "-" : - String.Empty) + FieldLength.ToString() : - String.Empty) + "}"; - - if (IsNumericType(Value)) - { - w = Convert.ToString(UnboxToLong(Value, true), 8); - - if (Left2Right || Padding == ' ') - { - if (Alternate && w != "0") - w = "0" + w; - w = String.Format(lengthFormat, w); - } - else - { - if (FieldLength != int.MinValue) - w = w.PadLeft(FieldLength - (Alternate && w != "0" ? 1 : 0), Padding); - if (Alternate && w != "0") - w = "0" + w; - } - } - - return w; - } - #endregion - #region FormatHEX - private static string FormatHex(string NativeFormat, bool Alternate, - int FieldLength, int FieldPrecision, - bool Left2Right, - char Padding, object Value) - { - string w = String.Empty; - string lengthFormat = "{0" + (FieldLength != int.MinValue ? - "," + (Left2Right ? - "-" : - String.Empty) + FieldLength.ToString() : - String.Empty) + "}"; - string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ? - FieldPrecision.ToString() : - String.Empty) + "}"; - - if (IsNumericType(Value)) - { - w = String.Format(numberFormat, Value); - - if (Left2Right || Padding == ' ') - { - if (Alternate) - w = (NativeFormat == "x" ? "0x" : "0X") + w; - w = String.Format(lengthFormat, w); - } - else - { - if (FieldLength != int.MinValue) - w = w.PadLeft(FieldLength - (Alternate ? 2 : 0), Padding); - if (Alternate) - w = (NativeFormat == "x" ? "0x" : "0X") + w; - } - } - - return w; - } - #endregion - #region FormatNumber - private static string FormatNumber(string NativeFormat, bool Alternate, - int FieldLength, int FieldPrecision, - bool Left2Right, - bool PositiveSign, bool PositiveSpace, - char Padding, object Value) - { - string w = String.Empty; - string lengthFormat = "{0" + (FieldLength != int.MinValue ? - "," + (Left2Right ? - "-" : - String.Empty) + FieldLength.ToString() : - String.Empty) + "}"; - string numberFormat = "{0:" + NativeFormat + (FieldPrecision != int.MinValue ? - FieldPrecision.ToString() : - "0") + "}"; - - if (IsNumericType(Value)) - { - w = String.Format(CultureInfo.InvariantCulture, numberFormat, Value); - - if (Left2Right || Padding == ' ') - { - if (IsPositive(Value, true)) - w = (PositiveSign ? - "+" : (PositiveSpace ? " " : String.Empty)) + w; - w = String.Format(lengthFormat, w); - } - else - { - if (w.StartsWith("-")) - w = w.Substring(1); - if (FieldLength != int.MinValue) - if (PositiveSign) // xan - change here - w = w.PadLeft(FieldLength - 1, Padding); - else - w = w.PadLeft(FieldLength, Padding); - if (IsPositive(Value, true)) - w = (PositiveSign ? - "+" : "") + w; // xan - change here - else - w = "-" + w; - } - } - - return w; - } - #endregion - #endregion - } -} - - diff --git a/src/MoonSharp.Interpreter/Tree/IVariable.cs b/src/MoonSharp.Interpreter/Tree/IVariable.cs deleted file mode 100644 index fa1e15c7..00000000 --- a/src/MoonSharp.Interpreter/Tree/IVariable.cs +++ /dev/null @@ -1,12 +0,0 @@ - -using MoonSharp.Interpreter.Tree.Expressions; - -namespace MoonSharp.Interpreter.Tree -{ - interface IVariable - { - void CompileAssignment(Execution.VM.ByteCode bc, Operator op, int stackofs, int tupleidx); - - bool IsAssignment { get; } - } -} diff --git a/src/MoonSharp.Interpreter/Tree/Lexer/LexerUtils.cs b/src/MoonSharp.Interpreter/Tree/Lexer/LexerUtils.cs deleted file mode 100755 index d7802bbb..00000000 --- a/src/MoonSharp.Interpreter/Tree/Lexer/LexerUtils.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace MoonSharp.Interpreter.Tree -{ - internal static class LexerUtils - { - public static double ParseNumber(Token T) - { - string txt = T.Text; - double res; - if (!double.TryParse(txt, NumberStyles.Float, CultureInfo.InvariantCulture, out res)) - throw new SyntaxErrorException(T, "malformed number near '{0}'", txt); - - return res; - } - - public static double ParseHexInteger(Token T) - { - string txt = T.Text; - if ((txt.Length < 2) || (txt[0] != '0' && (char.ToUpper(txt[1]) != 'X'))) - throw new InternalErrorException("hex numbers must start with '0x' near '{0}'.", txt); - - ulong res; - - if (!ulong.TryParse(txt.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out res)) - throw new SyntaxErrorException(T, "malformed number near '{0}'", txt); - - return (double)res; - } - - public static string ReadHexProgressive(string s, ref double d, out int digits) - { - digits = 0; - - for (int i = 0; i < s.Length; i++) - { - char c = s[i]; - - if (LexerUtils.CharIsHexDigit(c)) - { - int v = LexerUtils.HexDigit2Value(c); - d *= 16.0; - d += v; - ++digits; - } - else - { - return s.Substring(i); - } - } - - return string.Empty; - } - - public static double ParseHexFloat(Token T) - { - string s = T.Text; - - try - { - if ((s.Length < 2) || (s[0] != '0' && (char.ToUpper(s[1]) != 'X'))) - throw new InternalErrorException("hex float must start with '0x' near '{0}'", s); - - s = s.Substring(2); - - double value = 0.0; - int dummy, exp = 0; - - s = ReadHexProgressive(s, ref value, out dummy); - - if (s.Length > 0 && s[0] == '.') - { - s = s.Substring(1); - s = ReadHexProgressive(s, ref value, out exp); - } - - exp *= -4; - - if (s.Length > 0 && char.ToUpper(s[0]) == 'P') - { - if (s.Length == 1) - throw new SyntaxErrorException(T, "invalid hex float format near '{0}'", s); - - s = s.Substring(s[1] == '+' ? 2 : 1); - - int exp1 = int.Parse(s, CultureInfo.InvariantCulture); - - exp += exp1; - } - - double result = value * Math.Pow(2, exp); - return result; - } - catch (FormatException) - { - throw new SyntaxErrorException(T, "malformed number near '{0}'", s); - } - } - - - public static int HexDigit2Value(char c) - { - if (c >= '0' && c <= '9') - return c - '0'; - else if (c >= 'A' && c <= 'F') - return 10 + (c - 'A'); - else if (c >= 'a' && c <= 'f') - return 10 + (c - 'a'); - else - throw new InternalErrorException("invalid hex digit near '{0}'", c); - } - - public static bool CharIsDigit(char c) - { - return c >= '0' && c <= '9'; - } - - public static bool CharIsHexDigit(char c) - { - return CharIsDigit(c) || - c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f' || - c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F'; - } - - public static string AdjustLuaLongString(string str) - { - if (str.StartsWith("\r\n")) - str = str.Substring(2); - else if (str.StartsWith("\n")) - str = str.Substring(1); - - return str; - } - - public static string UnescapeLuaString(Token token, string str) - { - if (!str.Contains('\\')) - return str; - - StringBuilder sb = new StringBuilder(); - - bool escape = false; - bool hex = false; - int unicode_state = 0; - string hexprefix = ""; - string val = ""; - bool zmode = false; - - foreach (char c in str) - { - redo: - if (escape) - { - if (val.Length == 0 && !hex && unicode_state == 0) - { - if (c == 'a') { sb.Append('\a'); escape = false; zmode = false; } - else if (c == '\r') { } // this makes \\r\n -> \\n - else if (c == '\n') { sb.Append('\n'); escape = false; } - else if (c == 'b') { sb.Append('\b'); escape = false; } - else if (c == 'f') { sb.Append('\f'); escape = false; } - else if (c == 'n') { sb.Append('\n'); escape = false; } - else if (c == 'r') { sb.Append('\r'); escape = false; } - else if (c == 't') { sb.Append('\t'); escape = false; } - else if (c == 'v') { sb.Append('\v'); escape = false; } - else if (c == '\\') { sb.Append('\\'); escape = false; zmode = false; } - else if (c == '"') { sb.Append('\"'); escape = false; zmode = false; } - else if (c == '\'') { sb.Append('\''); escape = false; zmode = false; } - else if (c == '[') { sb.Append('['); escape = false; zmode = false; } - else if (c == ']') { sb.Append(']'); escape = false; zmode = false; } - else if (c == '{') { sb.Append('{'); escape = false; zmode = false; } - else if (c == 'x') { hex = true; } - else if (c == 'u') { unicode_state = 1; } - else if (c == 'z') { zmode = true; escape = false; } - else if (CharIsDigit(c)) { val = val + c; } - else throw new SyntaxErrorException(token, "invalid escape sequence near '\\{0}'", c); - } - else - { - if (unicode_state == 1) - { - if (c != '{') - throw new SyntaxErrorException(token, "'{' expected near '\\u'"); - - unicode_state = 2; - } - else if (unicode_state == 2) - { - if (c == '}') - { - int i = int.Parse(val, NumberStyles.HexNumber, CultureInfo.InvariantCulture); - sb.Append(ConvertUtf32ToChar(i)); - unicode_state = 0; - val = string.Empty; - escape = false; - } - else if (val.Length >= 8) - { - throw new SyntaxErrorException(token, "'}' missing, or unicode code point too large after '\\u'"); - } - else - { - val += c; - } - } - else if (hex) - { - if (CharIsHexDigit(c)) - { - val += c; - if (val.Length == 2) - { - int i = int.Parse(val, NumberStyles.HexNumber, CultureInfo.InvariantCulture); - sb.Append(ConvertUtf32ToChar(i)); - zmode = false; - escape = false; - } - } - else - { - throw new SyntaxErrorException(token, "hexadecimal digit expected near '\\{0}{1}{2}'", hexprefix, val, c); - } - } - else if (val.Length > 0) - { - if (CharIsDigit(c)) - { - val = val + c; - } - - if (val.Length == 3 || !CharIsDigit(c)) - { - int i = int.Parse(val, CultureInfo.InvariantCulture); - - if (i > 255) - throw new SyntaxErrorException(token, "decimal escape too large near '\\{0}'", val); - - sb.Append(ConvertUtf32ToChar(i)); - - zmode = false; - escape = false; - - if (!CharIsDigit(c)) - goto redo; - } - } - } - } - else - { - if (c == '\\') - { - escape = true; - hex = false; - val = ""; - } - else - { - if (!zmode || !char.IsWhiteSpace(c)) - { - sb.Append(c); - zmode = false; - } - } - } - } - - if (escape && !hex && val.Length > 0) - { - int i = int.Parse(val, CultureInfo.InvariantCulture); - sb.Append(ConvertUtf32ToChar(i)); - escape = false; - } - - if (escape) - { - throw new SyntaxErrorException(token, "unfinished string near '\"{0}\"'", sb.ToString()); - } - - return sb.ToString(); - } - - private static string ConvertUtf32ToChar(int i) - { - return char.ConvertFromUtf32(i); - } - - } -} diff --git a/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs deleted file mode 100644 index e31760b6..00000000 --- a/src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Collections.Generic; - -using MoonSharp.Interpreter.Execution; - - -namespace MoonSharp.Interpreter.Tree.Statements -{ - enum BlockEndType - { - Normal, - CloseCurly - } - class CompositeStatement : Statement - { - List m_Statements = new List(); - - public Token EndToken; - - public CompositeStatement(ScriptLoadingContext lcontext, BlockEndType endType) - : base(lcontext) - { - while (true) - { - ParseAnnotations(lcontext); - Token t = lcontext.Lexer.Current; - EndToken = lcontext.Lexer.Current; - if (t.IsEndOfBlock()) break; - if (endType == BlockEndType.CloseCurly && t.Type == TokenType.Brk_Close_Curly) break; - bool forceLast; - - Statement s = Statement.CreateStatement(lcontext, out forceLast); - m_Statements.Add(s); - EndToken = lcontext.Lexer.Current; - if (forceLast) break; - } - - // eat away all superfluos ';'s - while (lcontext.Lexer.Current.Type == TokenType.SemiColon) - lcontext.Lexer.Next(); - } - - public override void ResolveScope(ScriptLoadingContext lcontext) - { - if (lcontext.Syntax == ScriptSyntax.CLike) - { - //Perform declaration hoisting. - //Define all locals upfront, then bring function definitions up - List reordered = new List(m_Statements.Count); - foreach (var s in m_Statements) - { - if (s is AssignmentStatement a) - { - a.DefineLocals(lcontext); - reordered.Add(a); - } - else if (s is FunctionDefinitionStatement fd) - { - fd.DefineLocals(lcontext); - if(fd.CanHoist) - reordered.Insert(0, fd); - else - reordered.Add(fd); - } - else - { - reordered.Add(s); - } - } - m_Statements = reordered; - foreach(var s in m_Statements) s.ResolveScope(lcontext); - - } - else - { - foreach (var s in m_Statements) - { - if(s is AssignmentStatement a) a.DefineLocals(lcontext); - if(s is FunctionDefinitionStatement fd) fd.DefineLocals(lcontext); - s.ResolveScope(lcontext); - } - - } - - } - - - public override void Compile(Execution.VM.ByteCode bc) - { - if (m_Statements != null) - { - foreach (Statement s in m_Statements) - { - s.Compile(bc); - } - } - } - } -} diff --git a/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs deleted file mode 100644 index 6a82d639..00000000 --- a/src/MoonSharp.Interpreter/Tree/Statements/ForRangeStatement.cs +++ /dev/null @@ -1,113 +0,0 @@ -using MoonSharp.Interpreter.Debugging; -using MoonSharp.Interpreter.Execution; -using MoonSharp.Interpreter.Execution.VM; - -using MoonSharp.Interpreter.Tree.Expressions; - -namespace MoonSharp.Interpreter.Tree.Statements -{ - class ForRangeStatement : Statement, IBlockStatement - { - //for' NAME '=' exp ',' exp (',' exp)? 'do' block 'end' - RuntimeScopeBlock m_StackFrame; - Statement m_InnerBlock; - SymbolRef m_VarName; - Expression m_Start, m_End, m_Step; - SourceRef m_RefFor, m_RefEnd; - private Token nameToken; - - public SourceRef End => m_RefEnd; - - public ForRangeStatement(ScriptLoadingContext lcontext, Token nameToken, Token forToken, bool paren) : base(lcontext) - { - CheckTokenType(lcontext, TokenType.In); - var startNumber = CheckTokenType(lcontext, TokenType.Number).GetNumberValue(); - CheckTokenType(lcontext, TokenType.Op_Concat); - var endNumber = CheckTokenType(lcontext, TokenType.Number).GetNumberValue(); - m_Start = new LiteralExpression(lcontext, DynValue.NewNumber(startNumber)); - m_End = new LiteralExpression(lcontext, DynValue.NewNumber(endNumber)); - m_Step = new LiteralExpression(lcontext, DynValue.NewNumber(startNumber > endNumber ? -1 : 1)); - if (paren) CheckTokenType(lcontext, TokenType.Brk_Close_Round); - this.nameToken = nameToken; - - if (lcontext.Syntax == ScriptSyntax.Lua || lcontext.Lexer.Current.Type == TokenType.Do) - { - m_RefFor = forToken.GetSourceRef(CheckTokenType(lcontext, TokenType.Do)); - m_InnerBlock = new CompositeStatement(lcontext, BlockEndType.Normal); - m_RefEnd = CheckTokenType(lcontext, TokenType.End).GetSourceRef(); - } - else if (lcontext.Lexer.Current.Type == TokenType.Brk_Open_Curly) - { - m_RefFor = forToken.GetSourceRef(CheckTokenType(lcontext, TokenType.Brk_Open_Curly)); - m_InnerBlock = new CompositeStatement(lcontext, BlockEndType.CloseCurly); - m_RefEnd = CheckTokenType(lcontext, TokenType.Brk_Close_Curly).GetSourceRef(); - } - else - { - m_RefFor = forToken.GetSourceRef(lcontext.Lexer.Current); - m_InnerBlock = CreateStatement(lcontext, out _); - if (m_InnerBlock is IBlockStatement block) - m_RefEnd = block.End; - else - m_RefEnd = CheckTokenType(lcontext, TokenType.SemiColon).GetSourceRef(); - } - lcontext.Source.Refs.Add(m_RefFor); - lcontext.Source.Refs.Add(m_RefEnd); - } - - public override void ResolveScope(ScriptLoadingContext lcontext) - { - lcontext.Scope.PushBlock(); - m_VarName = lcontext.Scope.DefineLocal(nameToken.Text); - m_InnerBlock.ResolveScope(lcontext); - m_StackFrame = lcontext.Scope.PopBlock(); - } - - public override void Compile(ByteCode bc) - { - bc.PushSourceRef(m_RefFor); - - Loop L = new Loop() - { - Scope = m_StackFrame - }; - - bc.LoopTracker.Loops.Push(L); - - m_End.Compile(bc); - m_Step.Compile(bc); - m_Start.Compile(bc); - - int start = bc.GetJumpPointForNextInstruction(); - var jumpend = bc.Emit_Jump(OpCode.JFor, -1); - bc.Emit_Enter(m_StackFrame); - - bc.Emit_Store(m_VarName, 0, 0); - - m_InnerBlock.Compile(bc); - - bc.PopSourceRef(); - bc.PushSourceRef(m_RefEnd); - - int continuePoint = bc.GetJumpPointForNextInstruction(); - bc.Emit_Leave(m_StackFrame); - bc.Emit_Incr(1); - bc.Emit_Jump(OpCode.Jump, start); - - bc.LoopTracker.Loops.Pop(); - - int exitpoint = bc.GetJumpPointForNextInstruction(); - - foreach (int i in L.BreakJumps) - bc.SetNumVal(i, exitpoint); - foreach (int i in L.ContinueJumps) - bc.SetNumVal(i, continuePoint); - - bc.SetNumVal(jumpend, exitpoint); - bc.Emit_Pop(3); - - bc.PopSourceRef(); - } - - } -} \ No newline at end of file diff --git a/src/MoonSharp.Interpreter/Tree/Statements/IBlockStatement.cs b/src/MoonSharp.Interpreter/Tree/Statements/IBlockStatement.cs deleted file mode 100644 index 25bf9ff2..00000000 --- a/src/MoonSharp.Interpreter/Tree/Statements/IBlockStatement.cs +++ /dev/null @@ -1,9 +0,0 @@ -using MoonSharp.Interpreter.Debugging; - -namespace MoonSharp.Interpreter.Tree.Statements -{ - interface IBlockStatement - { - SourceRef End { get; } - } -} \ No newline at end of file diff --git a/src/MoonSharp.Tests/EndToEnd/CLikeTestRunner.cs b/src/MoonSharp.Tests/EndToEnd/CLikeTestRunner.cs deleted file mode 100644 index 988ca721..00000000 --- a/src/MoonSharp.Tests/EndToEnd/CLikeTestRunner.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.IO; -using System.Text; -using System.Threading.Tasks; -using NUnit.Framework; - -namespace MoonSharp.Interpreter.Tests; - -public class CLikeTestRunner -{ - private const string ROOT_FOLDER = "EndToEnd/CLike"; - - static string[] GetTestCases() - { - string[] files = Directory.GetFiles(ROOT_FOLDER, "*.lua*", SearchOption.AllDirectories); - - return files; - } - - [Test, TestCaseSource(nameof(GetTestCases))] - public async Task Run(string path) - { - string outputPath = path.Replace(".lua", ".txt"); - - if (!File.Exists(outputPath)) - { - Assert.Inconclusive($"Missing output file for test {path}"); - return; - } - - string code = await File.ReadAllTextAsync(path); - string output = await File.ReadAllTextAsync(outputPath); - StringBuilder stdOut = new StringBuilder(); - - Script script = new Script(CoreModules.Preset_HardSandbox); - script.Options.DebugPrint = s => stdOut.AppendLine(s); - script.Options.IndexTablesFrom = 0; - - if (path.Contains("SyntaxCLike")) - { - script.Options.Syntax = ScriptSyntax.CLike; - } - - if (path.Contains("flaky")) - { - Assert.Inconclusive($"Test {path} marked as flaky"); - return; - } - - try - { - await script.DoStringAsync(code); - Assert.AreEqual(output.Trim(), stdOut.ToString().Trim(), $"Test {path} did not pass."); - - if (path.Contains("invalid")) - { - Assert.Fail("Expected to crash but 'passed'"); - } - } - catch (Exception e) - { - if (e is AssertionException ae) - { - Assert.Fail($"Test {path} did not pass.\nMessage: {ae.Message}\n{ae.StackTrace}"); - return; - } - - if (path.Contains("invalid")) - { - Assert.Pass($"Crashed as expected: {e.Message}"); - return; - } - - Assert.Fail($"Test {path} did not pass.\nMessage: {e.Message}\n{e.StackTrace}"); - } - } -} \ No newline at end of file diff --git a/src/MoonSharp/Commands/ICommand.cs b/src/MoonSharp/Commands/ICommand.cs deleted file mode 100644 index 799bca5a..00000000 --- a/src/MoonSharp/Commands/ICommand.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MoonSharp.Commands -{ - interface ICommand - { - string Name { get; } - void DisplayShortHelp(); - void DisplayLongHelp(); - void Execute(ShellContext context, string argument); - } -} diff --git a/src/MoonSharp/Commands/Implementations/CompileCommand.cs b/src/MoonSharp/Commands/Implementations/CompileCommand.cs deleted file mode 100644 index 895741f2..00000000 --- a/src/MoonSharp/Commands/Implementations/CompileCommand.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using MoonSharp.Interpreter; - -namespace MoonSharp.Commands.Implementations -{ - class CompileCommand : ICommand - { - public string Name - { - get { return "compile"; } - } - - public void DisplayShortHelp() - { - Console.WriteLine("compile - Compiles the file in a binary format"); - } - - public void DisplayLongHelp() - { - Console.WriteLine("compile - Compiles the file in a binary format.\nThe destination filename will be appended with '-compiled'."); - } - - public void Execute(ShellContext context, string p) - { - string targetFileName = p + "-compiled"; - - Script S = new Script(CoreModules.None); - - DynValue chunk = S.LoadFile(p); - - using (Stream stream = new FileStream(targetFileName, FileMode.Create, FileAccess.Write)) - S.Dump(chunk, stream); - } - } -} diff --git a/src/MoonSharp/Commands/Implementations/HardWireCommand.cs b/src/MoonSharp/Commands/Implementations/HardWireCommand.cs deleted file mode 100644 index 078d0f61..00000000 --- a/src/MoonSharp/Commands/Implementations/HardWireCommand.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using MoonSharp.Hardwire; -using MoonSharp.Hardwire.Languages; -using MoonSharp.Interpreter; - -namespace MoonSharp.Commands.Implementations -{ - class HardWireCommand : ICommand - { - class ConsoleLogger : ICodeGenerationLogger - { - public int Errors = 0; - public int Warnings = 0; - - public void LogError(string message) - { - Console.WriteLine("[EE] - " + message); - ++Errors; - } - - public void LogWarning(string message) - { - Console.WriteLine("[ww] - " + message); - ++Warnings; - } - - public void LogMinor(string message) - { - Console.WriteLine("[ii] - " + message); - } - } - - - public string Name - { - get { return "hardwire"; } - } - - public void DisplayShortHelp() - { - Console.WriteLine("hardwire - Creates hardwire descriptors from a dump table (interactive). "); - } - - public void DisplayLongHelp() - { - Console.WriteLine("hardwire - Creates hardwire descriptors from a dump table (interactive). "); - Console.WriteLine(); - } - - public void Execute(ShellContext context, string argument) - { - Console.WriteLine("At any question, type #quit to abort."); - Console.WriteLine(); - - string language = AskQuestion("Language, cs or vb ? [cs] : ", - "cs", s => s == "cs" || s == "vb", "Must be 'cs' or 'vb'."); - - if (language == null) - return; - - string luafile = AskQuestion("Lua dump table file: ", - "", s => File.Exists(s), "File does not exists."); - - if (luafile == null) - return; - - string destfile = AskQuestion("Destination file: ", - "", s => true, ""); - - if (destfile == null) - return; - - string allowinternals = AskQuestion("Allow internals y/n ? [y]: ", - "y", s => s == "y" || s == "n", ""); - - if (allowinternals == null) - return; - - string namespaceName = AskQuestion("Namespace ? [HardwiredClasses]: ", - "HardwiredClasses", s => IsValidIdentifier(s), "Not a valid identifier."); - - if (namespaceName == null) - return; - - string className = AskQuestion("Class ? [HardwireTypes]: ", - "HardwireTypes", s => IsValidIdentifier(s), "Not a valid identifier."); - - if (className == null) - return; - - Generate(language, luafile, destfile, allowinternals == "y", className, namespaceName); - } - - private bool IsValidIdentifier(string s) - { - if (string.IsNullOrEmpty(s)) - return false; - - foreach (char c in s) - { - if (c != '_' && !char.IsLetterOrDigit(c)) - return false; - } - - if (char.IsDigit(s[0])) - return false; - - return true; - } - - public static void Generate(string language, string luafile, string destfile, bool allowInternals, string classname, string namespacename) - { - var logger = new ConsoleLogger(); - try - { - Script s = new Script(CoreModules.None); - var eee = s.CreateDynamicExpression(File.ReadAllText(luafile)); - - Table t = eee.Evaluate(null).Table; - - HardwireGeneratorRegistry.RegisterPredefined(); - - HardwireGenerator hcg = new HardwireGenerator(namespacename ?? "HardwiredClasses", classname ?? "HardwireTypes", logger, - language == "vb" ? HardwireCodeGenerationLanguage.VB : HardwireCodeGenerationLanguage.CSharp) - { - AllowInternals = allowInternals - }; - - hcg.BuildCodeModel(t); - - string code = hcg.GenerateSourceCode(); - - File.WriteAllText(destfile, code); - } - catch (Exception ex) - { - Console.WriteLine("Internal error : {0}", ex.Message); - } - - Console.WriteLine(); - Console.WriteLine("done: {0} errors, {1} warnings.", logger.Errors, logger.Warnings); - } - - string AskQuestion(string prompt, string defval, Func validator, string errormsg) - { - while (true) - { - Console.Write(prompt); - string inp = Console.ReadLine(); - - if (inp == "#quit") return null; - - if (inp == "") - inp = defval; - - if (validator(inp)) - return inp; - - Console.WriteLine(errormsg); - } - } - - - - - } -} diff --git a/src/MoonSharp/Commands/Implementations/RunCommand.cs b/src/MoonSharp/Commands/Implementations/RunCommand.cs deleted file mode 100644 index 31e1e481..00000000 --- a/src/MoonSharp/Commands/Implementations/RunCommand.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace MoonSharp.Commands.Implementations -{ - class RunCommand : ICommand - { - public string Name - { - get { return "run"; } - } - - public void DisplayShortHelp() - { - Console.WriteLine("run - Executes the specified Lua script"); - } - - public void DisplayLongHelp() - { - Console.WriteLine("run - Executes the specified Lua script."); - } - - public void Execute(ShellContext context, string arguments) - { - if (arguments.Length == 0) - { - Console.WriteLine("Syntax : !run "); - } - else - { - context.Script.DoFile(arguments); - } - } - } -} diff --git a/src/MoonSharp/MoonSharp.csproj b/src/MoonSharp/MoonSharp.csproj deleted file mode 100644 index 0f180b8e..00000000 --- a/src/MoonSharp/MoonSharp.csproj +++ /dev/null @@ -1,13 +0,0 @@ - - - - Exe - net6.0 - - - - - - - - diff --git a/src/MoonSharp/Program.cs b/src/MoonSharp/Program.cs deleted file mode 100755 index d6aa804c..00000000 --- a/src/MoonSharp/Program.cs +++ /dev/null @@ -1,219 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using MoonSharp.Commands; -using MoonSharp.Commands.Implementations; -using MoonSharp.Interpreter; -using MoonSharp.Interpreter.Execution; -using MoonSharp.Interpreter.Loaders; -using MoonSharp.Interpreter.REPL; -using MoonSharp.Interpreter.Serialization; - -namespace MoonSharp -{ - class Program - { - [STAThread] - static void Main(string[] args) - { - CommandManager.Initialize(); - - Script.DefaultOptions.ScriptLoader = new ReplInterpreterScriptLoader(); - - Script script = new Script(CoreModules.Preset_Complete); - - script.Globals["makestatic"] = (Func)(MakeStatic); - - if (CheckArgs(args, new ShellContext(script))) - return; - - Banner(); - - ReplInterpreter interpreter = new ReplInterpreter(script) - { - HandleDynamicExprs = true, - HandleClassicExprsSyntax = true - }; - - - while (true) - { - InterpreterLoop(interpreter, new ShellContext(script)); - } - } - - private static DynValue MakeStatic(string type) - { - Type tt = Type.GetType(type); - if (tt == null) - Console.WriteLine("Type '{0}' not found.", type); - else - return UserData.CreateStatic(tt); - - return DynValue.Nil; - } - - private static void InterpreterLoop(ReplInterpreter interpreter, ShellContext shellContext) - { - Console.Write(interpreter.ClassicPrompt + " "); - - string s = Console.ReadLine(); - - if (!interpreter.HasPendingCommand && s.StartsWith("!")) - { - ExecuteCommand(shellContext, s.Substring(1)); - return; - } - - try - { - DynValue result = interpreter.Evaluate(s); - - if (result.Type != DataType.Void) - Console.WriteLine("{0}", result); - } - catch (InterpreterException ex) - { - Console.WriteLine("{0}", ex.DecoratedMessage ?? ex.Message); - } - catch (Exception ex) - { - Console.WriteLine("{0}", ex.Message); - } - } - - private static void Banner() - { - Console.WriteLine(Script.GetBanner("Console")); - Console.WriteLine(); - Console.WriteLine("Type Lua code to execute it or type !help to see help on commands.\n"); - Console.WriteLine("Welcome.\n"); - } - - - private static bool CheckArgs(string[] args, ShellContext shellContext) - { - if (args.Length == 0) - return false; - - if (args.Length == 1 && args[0].Length > 0 && args[0][0] != '-') - { - Script script = new Script(); - script.DoFile(args[0]); - } - - if (args[0] == "-H" || args[0] == "--help" || args[0] == "/?" || args[0] == "-?") - { - ShowCmdLineHelpBig(); - } - else if (args[0] == "-X") - { - if (args.Length == 2) - { - ExecuteCommand(shellContext, args[1]); - } - else - { - Console.WriteLine("Wrong syntax."); - ShowCmdLineHelp(); - } - } - else if (args[0] == "-W") - { - bool internals = false; - string dumpfile = null; - string destfile = null; - string classname = null; - string namespacename = null; - bool useVb = false; - bool fail = true; - - for (int i = 1; i < args.Length; i++) - { - if (args[i] == "--internals") - internals = true; - else if (args[i] == "--vb") - useVb = true; - else if (args[i].StartsWith("--class:")) - classname = args[i].Substring("--class:".Length); - else if (args[i].StartsWith("--namespace:")) - namespacename = args[i].Substring("--namespace:".Length); - else if (dumpfile == null) - dumpfile = args[i]; - else if (destfile == null) - { - destfile = args[i]; - fail = false; - } - else fail = true; - } - - if (fail) - { - Console.WriteLine("Wrong syntax."); - ShowCmdLineHelp(); - } - else - { - HardWireCommand.Generate(useVb ? "vb" : "cs", dumpfile, destfile, internals, classname, namespacename); - } - } - - return true; - } - - private static void ShowCmdLineHelpBig() - { - Console.WriteLine("usage: moonsharp [-H | --help | -X \"command\" | -W [--internals] [--vb] [--class:] [--namespace:] |