Christopher
8 years ago
577 changed files with 40593 additions and 8143 deletions
@ -0,0 +1,36 @@ |
|||||||
|
{ |
||||||
|
"version": "0.2.0", |
||||||
|
"configurations": [ |
||||||
|
{ |
||||||
|
"name": "Unity Editor", |
||||||
|
"type": "unity", |
||||||
|
"request": "launch" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Windows Player", |
||||||
|
"type": "unity", |
||||||
|
"request": "launch" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "OSX Player", |
||||||
|
"type": "unity", |
||||||
|
"request": "launch" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Linux Player", |
||||||
|
"type": "unity", |
||||||
|
"request": "launch" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "iOS Player", |
||||||
|
"type": "unity", |
||||||
|
"request": "launch" |
||||||
|
}, |
||||||
|
{ |
||||||
|
"name": "Android Player", |
||||||
|
"type": "unity", |
||||||
|
"request": "launch" |
||||||
|
|
||||||
|
} |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
{ |
||||||
|
"files.exclude": |
||||||
|
{ |
||||||
|
"**/.DS_Store":true, |
||||||
|
"**/.git":true, |
||||||
|
"**/.gitignore":true, |
||||||
|
"**/.gitattributes":true, |
||||||
|
"**/.gitmodules":true, |
||||||
|
"**/.svn":true, |
||||||
|
"**/*.booproj":true, |
||||||
|
"**/*.pidb":true, |
||||||
|
"**/*.suo":true, |
||||||
|
"**/*.user":true, |
||||||
|
"**/*.userprefs":true, |
||||||
|
"**/*.unityproj":true, |
||||||
|
"**/*.dll":true, |
||||||
|
"**/*.exe":true, |
||||||
|
"**/*.pdf":true, |
||||||
|
"**/*.mid":true, |
||||||
|
"**/*.midi":true, |
||||||
|
"**/*.wav":true, |
||||||
|
"**/*.gif":true, |
||||||
|
"**/*.ico":true, |
||||||
|
"**/*.jpg":true, |
||||||
|
"**/*.jpeg":true, |
||||||
|
"**/*.png":true, |
||||||
|
"**/*.psd":true, |
||||||
|
"**/*.tga":true, |
||||||
|
"**/*.tif":true, |
||||||
|
"**/*.tiff":true, |
||||||
|
"**/*.3ds":true, |
||||||
|
"**/*.3DS":true, |
||||||
|
"**/*.fbx":true, |
||||||
|
"**/*.FBX":true, |
||||||
|
"**/*.lxo":true, |
||||||
|
"**/*.LXO":true, |
||||||
|
"**/*.ma":true, |
||||||
|
"**/*.MA":true, |
||||||
|
"**/*.obj":true, |
||||||
|
"**/*.OBJ":true, |
||||||
|
"**/*.asset":true, |
||||||
|
"**/*.cubemap":true, |
||||||
|
"**/*.flare":true, |
||||||
|
"**/*.mat":true, |
||||||
|
"**/*.meta":true, |
||||||
|
"**/*.prefab":true, |
||||||
|
"**/*.unity":true, |
||||||
|
"build/":true, |
||||||
|
"Build/":true, |
||||||
|
"Library/":true, |
||||||
|
"library/":true, |
||||||
|
"obj/":true, |
||||||
|
"Obj/":true, |
||||||
|
"ProjectSettings/":true,
"temp/":true, |
||||||
|
"Temp/":true |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: fe983e267963641219d60f73a36907ce |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 71b4d33685e4746ca9cfe341d75910d9 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1476112669 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,316 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Text.RegularExpressions; |
||||||
|
using System.Threading; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.Interpreter.Debugging; |
||||||
|
using MoonSharp.VsCodeDebugger; |
||||||
|
using MoonSharp.VsCodeDebugger.SDK; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.DebuggerLogic |
||||||
|
{ |
||||||
|
internal class AsyncDebugger : IDebugger |
||||||
|
{ |
||||||
|
private static object s_AsyncDebuggerIdLock = new object(); |
||||||
|
private static int s_AsyncDebuggerIdCounter = 0; |
||||||
|
|
||||||
|
object m_Lock = new object(); |
||||||
|
private IAsyncDebuggerClient m_Client__; |
||||||
|
DebuggerAction m_PendingAction = null; |
||||||
|
|
||||||
|
List<WatchItem>[] m_WatchItems; |
||||||
|
Dictionary<int, SourceCode> m_SourcesMap = new Dictionary<int, SourceCode>(); |
||||||
|
Dictionary<int, string> m_SourcesOverride = new Dictionary<int, string>(); |
||||||
|
Func<SourceCode, string> m_SourceFinder; |
||||||
|
|
||||||
|
|
||||||
|
public DebugService DebugService { get; private set; } |
||||||
|
|
||||||
|
public Regex ErrorRegex { get; set; } |
||||||
|
|
||||||
|
public Script Script { get; private set; } |
||||||
|
|
||||||
|
public bool PauseRequested { get; set; } |
||||||
|
|
||||||
|
public string Name { get; set; } |
||||||
|
|
||||||
|
public int Id { get; private set; } |
||||||
|
|
||||||
|
|
||||||
|
public AsyncDebugger(Script script, Func<SourceCode, string> sourceFinder, string name) |
||||||
|
{ |
||||||
|
lock (s_AsyncDebuggerIdLock) |
||||||
|
Id = s_AsyncDebuggerIdCounter++; |
||||||
|
|
||||||
|
m_SourceFinder = sourceFinder; |
||||||
|
ErrorRegex = new Regex(@"\A.*\Z"); |
||||||
|
Script = script; |
||||||
|
m_WatchItems = new List<WatchItem>[(int)WatchType.MaxValue]; |
||||||
|
Name = name; |
||||||
|
|
||||||
|
for (int i = 0; i < m_WatchItems.Length; i++) |
||||||
|
m_WatchItems[i] = new List<WatchItem>(64); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public IAsyncDebuggerClient Client |
||||||
|
{ |
||||||
|
get { return m_Client__; } |
||||||
|
set |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (m_Client__ != null && m_Client__ != value) |
||||||
|
{ |
||||||
|
m_Client__.Unbind(); |
||||||
|
} |
||||||
|
|
||||||
|
if (value != null) |
||||||
|
{ |
||||||
|
for (int i = 0; i < Script.SourceCodeCount; i++) |
||||||
|
if (m_SourcesMap.ContainsKey(i)) |
||||||
|
value.OnSourceCodeChanged(i); |
||||||
|
} |
||||||
|
|
||||||
|
m_Client__ = value; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
DebuggerAction IDebugger.GetAction(int ip, SourceRef sourceref) |
||||||
|
{ |
||||||
|
PauseRequested = false; |
||||||
|
|
||||||
|
lock (m_Lock) |
||||||
|
if (Client != null) |
||||||
|
{ |
||||||
|
Client.SendStopEvent(); |
||||||
|
} |
||||||
|
|
||||||
|
while (true) |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (Client == null) |
||||||
|
{ |
||||||
|
return new DebuggerAction() { Action = DebuggerAction.ActionType.Run }; |
||||||
|
} |
||||||
|
|
||||||
|
if (m_PendingAction != null) |
||||||
|
{ |
||||||
|
var action = m_PendingAction; |
||||||
|
m_PendingAction = null; |
||||||
|
return action; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Sleep(10); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void QueueAction(DebuggerAction action) |
||||||
|
{ |
||||||
|
while (true) |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
if (m_PendingAction == null) |
||||||
|
{ |
||||||
|
m_PendingAction = action; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
Sleep(10); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void Sleep(int v) |
||||||
|
{ |
||||||
|
#if DOTNET_CORE |
||||||
|
System.Threading.Tasks.Task.Delay(10).Wait(); |
||||||
|
#else |
||||||
|
System.Threading.Thread.Sleep(10); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
private DynamicExpression CreateDynExpr(string code) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
return Script.CreateDynamicExpression(code); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
return Script.CreateConstantDynamicExpression(code, DynValue.NewString(ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
List<DynamicExpression> IDebugger.GetWatchItems() |
||||||
|
{ |
||||||
|
return new List<DynamicExpression>(); |
||||||
|
} |
||||||
|
|
||||||
|
bool IDebugger.IsPauseRequested() |
||||||
|
{ |
||||||
|
return PauseRequested; |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugger.RefreshBreakpoints(IEnumerable<SourceRef> refs) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void IDebugger.SetByteCode(string[] byteCode) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void IDebugger.SetSourceCode(SourceCode sourceCode) |
||||||
|
{ |
||||||
|
m_SourcesMap[sourceCode.SourceID] = sourceCode; |
||||||
|
|
||||||
|
bool invalidFile = false; |
||||||
|
|
||||||
|
string file = m_SourceFinder(sourceCode); |
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(file)) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
if (!File.Exists(file)) |
||||||
|
invalidFile = true; |
||||||
|
} |
||||||
|
catch |
||||||
|
{ |
||||||
|
invalidFile = true; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
invalidFile = true; |
||||||
|
} |
||||||
|
|
||||||
|
if (invalidFile) |
||||||
|
{ |
||||||
|
file = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N") + ".lua"); |
||||||
|
File.WriteAllText(file, sourceCode.Code + GetFooterForTempFile()); |
||||||
|
m_SourcesOverride[sourceCode.SourceID] = file; |
||||||
|
} |
||||||
|
else if (file != sourceCode.Name) |
||||||
|
{ |
||||||
|
m_SourcesOverride[sourceCode.SourceID] = file; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
lock (m_Lock) |
||||||
|
if (Client != null) |
||||||
|
Client.OnSourceCodeChanged(sourceCode.SourceID); |
||||||
|
} |
||||||
|
|
||||||
|
private string GetFooterForTempFile() |
||||||
|
{ |
||||||
|
return "\n\n" + |
||||||
|
"----------------------------------------------------------------------------------------------------------\n" + |
||||||
|
"-- This file has been generated by the debugger as a placeholder for a script snippet stored in memory. --\n" + |
||||||
|
"-- If you restart the host process, the contents of this file are not valid anymore. --\n" + |
||||||
|
"----------------------------------------------------------------------------------------------------------\n"; |
||||||
|
} |
||||||
|
|
||||||
|
public string GetSourceFile(int sourceId) |
||||||
|
{ |
||||||
|
if (m_SourcesOverride.ContainsKey(sourceId)) |
||||||
|
return m_SourcesOverride[sourceId]; |
||||||
|
else if (m_SourcesMap.ContainsKey(sourceId)) |
||||||
|
return m_SourcesMap[sourceId].Name; |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsSourceOverride(int sourceId) |
||||||
|
{ |
||||||
|
return (m_SourcesOverride.ContainsKey(sourceId)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void IDebugger.SignalExecutionEnded() |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
if (Client != null) |
||||||
|
Client.OnExecutionEnded(); |
||||||
|
} |
||||||
|
|
||||||
|
bool IDebugger.SignalRuntimeException(ScriptRuntimeException ex) |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
if (Client == null) |
||||||
|
return false; |
||||||
|
|
||||||
|
Client.OnException(ex); |
||||||
|
PauseRequested = ErrorRegex.IsMatch(ex.Message); |
||||||
|
return PauseRequested; |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugger.Update(WatchType watchType, IEnumerable<WatchItem> items) |
||||||
|
{ |
||||||
|
var list = m_WatchItems[(int)watchType]; |
||||||
|
|
||||||
|
list.Clear(); |
||||||
|
list.AddRange(items); |
||||||
|
|
||||||
|
lock (m_Lock) |
||||||
|
if (Client != null) |
||||||
|
Client.OnWatchesUpdated(watchType); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public List<WatchItem> GetWatches(WatchType watchType) |
||||||
|
{ |
||||||
|
return m_WatchItems[(int)watchType]; |
||||||
|
} |
||||||
|
|
||||||
|
public SourceCode GetSource(int id) |
||||||
|
{ |
||||||
|
if (m_SourcesMap.ContainsKey(id)) |
||||||
|
return m_SourcesMap[id]; |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public SourceCode FindSourceByName(string path) |
||||||
|
{ |
||||||
|
// we use case insensitive match - be damned if you have files which differ only by |
||||||
|
// case in the same directory on Unix. |
||||||
|
path = path.Replace('\\', '/').ToUpperInvariant(); |
||||||
|
|
||||||
|
foreach (var kvp in m_SourcesOverride) |
||||||
|
{ |
||||||
|
if (kvp.Value.Replace('\\', '/').ToUpperInvariant() == path) |
||||||
|
return m_SourcesMap[kvp.Key]; |
||||||
|
} |
||||||
|
|
||||||
|
return m_SourcesMap.Values.FirstOrDefault(s => s.Name.Replace('\\', '/').ToUpperInvariant() == path); |
||||||
|
} |
||||||
|
|
||||||
|
void IDebugger.SetDebugService(DebugService debugService) |
||||||
|
{ |
||||||
|
DebugService = debugService; |
||||||
|
} |
||||||
|
|
||||||
|
public DynValue Evaluate(string expression) |
||||||
|
{ |
||||||
|
DynamicExpression expr = CreateDynExpr(expression); |
||||||
|
return expr.Evaluate(); |
||||||
|
} |
||||||
|
|
||||||
|
DebuggerCaps IDebugger.GetDebuggerCaps() |
||||||
|
{ |
||||||
|
return DebuggerCaps.CanDebugSourceCode | DebuggerCaps.HasLineBasedBreakpoints; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 9984211c3fbdf48d2bab7bc81675b60f |
||||||
|
timeCreated: 1476432885 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,209 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.VsCodeDebugger.SDK; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.DebuggerLogic |
||||||
|
{ |
||||||
|
internal class EmptyDebugSession : DebugSession |
||||||
|
{ |
||||||
|
MoonSharpVsCodeDebugServer m_Server; |
||||||
|
|
||||||
|
internal EmptyDebugSession(MoonSharpVsCodeDebugServer server) |
||||||
|
: base(true, false) |
||||||
|
{ |
||||||
|
m_Server = server; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Initialize(Response response, Table args) |
||||||
|
{ |
||||||
|
#if DOTNET_CORE |
||||||
|
SendText("Connected to MoonSharp {0} [{1}]", |
||||||
|
Script.VERSION, |
||||||
|
Script.GlobalOptions.Platform.GetPlatformName()); |
||||||
|
#else |
||||||
|
SendText("Connected to MoonSharp {0} [{1}] on process {2} (PID {3})", |
||||||
|
Script.VERSION, |
||||||
|
Script.GlobalOptions.Platform.GetPlatformName(), |
||||||
|
System.Diagnostics.Process.GetCurrentProcess().ProcessName, |
||||||
|
System.Diagnostics.Process.GetCurrentProcess().Id); |
||||||
|
#endif |
||||||
|
|
||||||
|
SendText("No script is set as default for debugging; use the debug console to select the script to debug.\n"); |
||||||
|
|
||||||
|
SendList(); |
||||||
|
|
||||||
|
SendResponse(response, new Capabilities() |
||||||
|
{ |
||||||
|
// This debug adapter does not need the configurationDoneRequest. |
||||||
|
supportsConfigurationDoneRequest = false, |
||||||
|
|
||||||
|
// This debug adapter does not support function breakpoints. |
||||||
|
supportsFunctionBreakpoints = false, |
||||||
|
|
||||||
|
// This debug adapter doesn't support conditional breakpoints. |
||||||
|
supportsConditionalBreakpoints = false, |
||||||
|
|
||||||
|
// This debug adapter does not support a side effect free evaluate request for data hovers. |
||||||
|
supportsEvaluateForHovers = false, |
||||||
|
|
||||||
|
// This debug adapter does not support exception breakpoint filters |
||||||
|
exceptionBreakpointFilters = new object[0] |
||||||
|
}); |
||||||
|
|
||||||
|
// Debugger is ready to accept breakpoints immediately |
||||||
|
SendEvent(new InitializedEvent()); |
||||||
|
} |
||||||
|
|
||||||
|
private void SendList() |
||||||
|
{ |
||||||
|
int currId = m_Server.CurrentId ?? -1000; |
||||||
|
|
||||||
|
SendText("=========================================================="); |
||||||
|
|
||||||
|
foreach (var pair in m_Server.GetAttachedDebuggersByIdAndName()) |
||||||
|
{ |
||||||
|
string isdef = (pair.Key == currId) ? " (default)" : ""; |
||||||
|
SendText("{0} : {1}{2}", pair.Key.ToString().PadLeft(9), pair.Value, isdef); |
||||||
|
} |
||||||
|
SendText(""); |
||||||
|
SendText("Type the number of the script to debug, or '!' to refresh"); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Attach(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Continue(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendList(); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Disconnect(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
private static string getString(Table args, string property, string dflt = null) |
||||||
|
{ |
||||||
|
var s = (string)args[property]; |
||||||
|
if (s == null) |
||||||
|
{ |
||||||
|
return dflt; |
||||||
|
} |
||||||
|
s = s.Trim(); |
||||||
|
if (s.Length == 0) |
||||||
|
{ |
||||||
|
return dflt; |
||||||
|
} |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Evaluate(Response response, Table args) |
||||||
|
{ |
||||||
|
var expression = getString(args, "expression"); |
||||||
|
var context = getString(args, "context") ?? "hover"; |
||||||
|
|
||||||
|
if (context == "repl") |
||||||
|
ExecuteRepl(expression); |
||||||
|
|
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
private void ExecuteRepl(string cmd) |
||||||
|
{ |
||||||
|
int id = 0; |
||||||
|
if (int.TryParse(cmd, out id)) |
||||||
|
{ |
||||||
|
m_Server.CurrentId = id; |
||||||
|
|
||||||
|
SendText("Re-attach the debugger to debug the selected script."); |
||||||
|
|
||||||
|
Unbind(); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
SendList(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override void Launch(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Next(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendList(); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Pause(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendList(); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Scopes(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void SetBreakpoints(Response response, Table args) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void StackTrace(Response response, Table args) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override void StepIn(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendList(); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void StepOut(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendList(); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Threads(Response response, Table arguments) |
||||||
|
{ |
||||||
|
var threads = new List<Thread>() { new Thread(0, "Main Thread") }; |
||||||
|
SendResponse(response, new ThreadsResponseBody(threads)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override void Variables(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void SendText(string msg, params object[] args) |
||||||
|
{ |
||||||
|
msg = string.Format(msg, args); |
||||||
|
SendEvent(new OutputEvent("console", msg + "\n")); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void Unbind() |
||||||
|
{ |
||||||
|
SendText("Bye."); |
||||||
|
SendEvent(new TerminatedEvent()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: e92a4cfb128864cc1a914e4f59b2c73e |
||||||
|
timeCreated: 1476432887 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,23 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.Interpreter.Debugging; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.DebuggerLogic |
||||||
|
{ |
||||||
|
internal interface IAsyncDebuggerClient |
||||||
|
{ |
||||||
|
void SendStopEvent(); |
||||||
|
void OnWatchesUpdated(WatchType watchType); |
||||||
|
void OnSourceCodeChanged(int sourceID); |
||||||
|
void OnExecutionEnded(); |
||||||
|
void OnException(ScriptRuntimeException ex); |
||||||
|
void Unbind(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 439fb2da136aa426ab021def5caf0f6e |
||||||
|
timeCreated: 1476265156 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,460 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Text.RegularExpressions; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.Interpreter.Debugging; |
||||||
|
using MoonSharp.VsCodeDebugger.SDK; |
||||||
|
|
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.DebuggerLogic |
||||||
|
{ |
||||||
|
internal class MoonSharpDebugSession : DebugSession, IAsyncDebuggerClient |
||||||
|
{ |
||||||
|
AsyncDebugger m_Debug; |
||||||
|
MoonSharpVsCodeDebugServer m_Server; |
||||||
|
List<DynValue> m_Variables = new List<DynValue>(); |
||||||
|
bool m_NotifyExecutionEnd = false; |
||||||
|
|
||||||
|
const int SCOPE_LOCALS = 65536; |
||||||
|
const int SCOPE_SELF = 65537; |
||||||
|
|
||||||
|
|
||||||
|
internal MoonSharpDebugSession(MoonSharpVsCodeDebugServer server, AsyncDebugger debugger) |
||||||
|
: base(true, false) |
||||||
|
{ |
||||||
|
m_Server = server; |
||||||
|
m_Debug = debugger; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Initialize(Response response, Table args) |
||||||
|
{ |
||||||
|
#if DOTNET_CORE |
||||||
|
SendText("Connected to MoonSharp {0} [{1}]", |
||||||
|
Script.VERSION, |
||||||
|
Script.GlobalOptions.Platform.GetPlatformName()); |
||||||
|
#else |
||||||
|
SendText("Connected to MoonSharp {0} [{1}] on process {2} (PID {3})", |
||||||
|
Script.VERSION, |
||||||
|
Script.GlobalOptions.Platform.GetPlatformName(), |
||||||
|
System.Diagnostics.Process.GetCurrentProcess().ProcessName, |
||||||
|
System.Diagnostics.Process.GetCurrentProcess().Id); |
||||||
|
#endif |
||||||
|
|
||||||
|
SendText("Debugging script '{0}'; use the debug console to debug another script.", m_Debug.Name); |
||||||
|
|
||||||
|
SendText("Type '!help' in the Debug Console for available commands."); |
||||||
|
|
||||||
|
SendResponse(response, new Capabilities() |
||||||
|
{ |
||||||
|
// This debug adapter does not need the configurationDoneRequest. |
||||||
|
supportsConfigurationDoneRequest = false, |
||||||
|
|
||||||
|
// This debug adapter does not support function breakpoints. |
||||||
|
supportsFunctionBreakpoints = false, |
||||||
|
|
||||||
|
// This debug adapter doesn't support conditional breakpoints. |
||||||
|
supportsConditionalBreakpoints = false, |
||||||
|
|
||||||
|
// This debug adapter does not support a side effect free evaluate request for data hovers. |
||||||
|
supportsEvaluateForHovers = false, |
||||||
|
|
||||||
|
// This debug adapter does not support exception breakpoint filters |
||||||
|
exceptionBreakpointFilters = new object[0] |
||||||
|
}); |
||||||
|
|
||||||
|
// Debugger is ready to accept breakpoints immediately |
||||||
|
SendEvent(new InitializedEvent()); |
||||||
|
|
||||||
|
m_Debug.Client = this; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Attach(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Continue(Response response, Table arguments) |
||||||
|
{ |
||||||
|
m_Debug.QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.Run }); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Disconnect(Response response, Table arguments) |
||||||
|
{ |
||||||
|
m_Debug.Client = null; |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
private static string getString(Table args, string property, string dflt = null) |
||||||
|
{ |
||||||
|
var s = (string)args[property]; |
||||||
|
if (s == null) |
||||||
|
{ |
||||||
|
return dflt; |
||||||
|
} |
||||||
|
s = s.Trim(); |
||||||
|
if (s.Length == 0) |
||||||
|
{ |
||||||
|
return dflt; |
||||||
|
} |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Evaluate(Response response, Table args) |
||||||
|
{ |
||||||
|
var expression = getString(args, "expression"); |
||||||
|
var frameId = getInt(args, "frameId", 0); |
||||||
|
var context = getString(args, "context") ?? "hover"; |
||||||
|
|
||||||
|
if (frameId != 0 && context != "repl") |
||||||
|
SendText("Warning : Evaluation of variables/watches is always done with the top-level scope."); |
||||||
|
|
||||||
|
if (context == "repl" && expression.StartsWith("!")) |
||||||
|
{ |
||||||
|
ExecuteRepl(expression.Substring(1)); |
||||||
|
SendResponse(response); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
DynValue v = m_Debug.Evaluate(expression) ?? DynValue.Nil; |
||||||
|
m_Variables.Add(v); |
||||||
|
|
||||||
|
SendResponse(response, new EvaluateResponseBody(v.ToDebugPrintString(), m_Variables.Count - 1) |
||||||
|
{ |
||||||
|
type = v.Type.ToLuaDebuggerString() |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
private void ExecuteRepl(string cmd) |
||||||
|
{ |
||||||
|
bool showHelp = false; |
||||||
|
cmd = cmd.Trim(); |
||||||
|
if (cmd == "help") |
||||||
|
{ |
||||||
|
showHelp = true; |
||||||
|
} |
||||||
|
else if (cmd.StartsWith("geterror")) |
||||||
|
{ |
||||||
|
SendText("Current error regex : {0}", m_Debug.ErrorRegex.ToString()); |
||||||
|
} |
||||||
|
else if (cmd.StartsWith("seterror")) |
||||||
|
{ |
||||||
|
string regex = cmd.Substring("seterror".Length).Trim(); |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
Regex rx = new Regex(regex); |
||||||
|
m_Debug.ErrorRegex = rx; |
||||||
|
SendText("Current error regex : {0}", m_Debug.ErrorRegex.ToString()); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
SendText("Error setting regex: {0}", ex.Message); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (cmd.StartsWith("execendnotify")) |
||||||
|
{ |
||||||
|
string val = cmd.Substring("execendnotify".Length).Trim(); |
||||||
|
|
||||||
|
if (val == "off") |
||||||
|
{ |
||||||
|
m_NotifyExecutionEnd = false; |
||||||
|
} |
||||||
|
else if (val == "on") |
||||||
|
{ |
||||||
|
m_NotifyExecutionEnd = true; |
||||||
|
} |
||||||
|
else if (val.Length > 0) |
||||||
|
SendText("Error : expected 'on' or 'off'"); |
||||||
|
|
||||||
|
SendText("Notifications of execution end are : {0}", m_NotifyExecutionEnd ? "enabled" : "disabled"); |
||||||
|
} |
||||||
|
else if (cmd == "list") |
||||||
|
{ |
||||||
|
int currId = m_Server.CurrentId ?? -1000; |
||||||
|
|
||||||
|
foreach (var pair in m_Server.GetAttachedDebuggersByIdAndName()) |
||||||
|
{ |
||||||
|
string isthis = (pair.Key == m_Debug.Id) ? " (this)" : ""; |
||||||
|
string isdef = (pair.Key == currId) ? " (default)" : ""; |
||||||
|
|
||||||
|
SendText("{0} : {1}{2}{3}", pair.Key.ToString().PadLeft(9), pair.Value, isdef, isthis); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (cmd.StartsWith("select") || cmd.StartsWith("switch")) |
||||||
|
{ |
||||||
|
string arg = cmd.Substring("switch".Length).Trim(); |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
int id = int.Parse(arg); |
||||||
|
m_Server.CurrentId = id; |
||||||
|
|
||||||
|
if (cmd.StartsWith("switch")) |
||||||
|
Unbind(); |
||||||
|
else |
||||||
|
SendText("Next time you'll attach the debugger, it will be atteched to script #{0}", id); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
SendText("Error setting regex: {0}", ex.Message); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
SendText("Syntax error : {0}\n", cmd); |
||||||
|
showHelp = true; |
||||||
|
} |
||||||
|
|
||||||
|
if (showHelp) |
||||||
|
{ |
||||||
|
SendText("Available commands : "); |
||||||
|
SendText(" !help - gets this help"); |
||||||
|
SendText(" !list - lists the other scripts which can be debugged"); |
||||||
|
SendText(" !select <id> - select another script for future sessions"); |
||||||
|
SendText(" !switch <id> - switch to another script (same as select + disconnect)"); |
||||||
|
SendText(" !seterror <regex> - sets the regex which tells which errors to trap"); |
||||||
|
SendText(" !geterror - gets the current value of the regex which tells which errors to trap"); |
||||||
|
SendText(" !execendnotify [on|off] - sets the notification of end of execution on or off (default = off)"); |
||||||
|
SendText(" ... or type an expression to evaluate it on the fly."); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override void Launch(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Next(Response response, Table arguments) |
||||||
|
{ |
||||||
|
m_Debug.QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOver }); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
private StoppedEvent CreateStoppedEvent(string reason, string text = null) |
||||||
|
{ |
||||||
|
return new StoppedEvent(0, reason, text); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Pause(Response response, Table arguments) |
||||||
|
{ |
||||||
|
m_Debug.PauseRequested = true; |
||||||
|
SendResponse(response); |
||||||
|
SendText("Pause pending -- will pause at first script statement."); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Scopes(Response response, Table arguments) |
||||||
|
{ |
||||||
|
var scopes = new List<Scope>(); |
||||||
|
|
||||||
|
scopes.Add(new Scope("Locals", SCOPE_LOCALS)); |
||||||
|
scopes.Add(new Scope("Self", SCOPE_SELF)); |
||||||
|
|
||||||
|
SendResponse(response, new ScopesResponseBody(scopes)); |
||||||
|
} |
||||||
|
|
||||||
|
public override void SetBreakpoints(Response response, Table args) |
||||||
|
{ |
||||||
|
string path = null; |
||||||
|
|
||||||
|
Table args_source = args["source"] as Table; |
||||||
|
|
||||||
|
if (args_source != null) |
||||||
|
{ |
||||||
|
string p = args_source["path"].ToString(); |
||||||
|
if (p != null && p.Trim().Length > 0) |
||||||
|
path = p; |
||||||
|
} |
||||||
|
|
||||||
|
if (path == null) |
||||||
|
{ |
||||||
|
SendErrorResponse(response, 3010, "setBreakpoints: property 'source' is empty or misformed", null, false, true); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
path = ConvertClientPathToDebugger(path); |
||||||
|
|
||||||
|
SourceCode src = m_Debug.FindSourceByName(path); |
||||||
|
|
||||||
|
if (src == null) |
||||||
|
{ |
||||||
|
// we only support breakpoints in files mono can handle |
||||||
|
SendResponse(response, new SetBreakpointsResponseBody()); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
Table clientLines = args.Get("lines").Table; |
||||||
|
|
||||||
|
var lin = new HashSet<int>(clientLines.Values.Select(jt => ConvertClientLineToDebugger(jt.ToObject<int>())).ToArray()); |
||||||
|
|
||||||
|
var lin2 = m_Debug.DebugService.ResetBreakPoints(src, lin); |
||||||
|
|
||||||
|
var breakpoints = new List<Breakpoint>(); |
||||||
|
foreach (var l in lin) |
||||||
|
{ |
||||||
|
breakpoints.Add(new Breakpoint(lin2.Contains(l), l)); |
||||||
|
} |
||||||
|
|
||||||
|
response.SetBody(new SetBreakpointsResponseBody(breakpoints)); SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void StackTrace(Response response, Table args) |
||||||
|
{ |
||||||
|
int maxLevels = getInt(args, "levels", 10); |
||||||
|
//int threadReference = getInt(args, "threadId", 0); |
||||||
|
|
||||||
|
var stackFrames = new List<StackFrame>(); |
||||||
|
|
||||||
|
var stack = m_Debug.GetWatches(WatchType.CallStack); |
||||||
|
|
||||||
|
var coroutine = m_Debug.GetWatches(WatchType.Threads).LastOrDefault(); |
||||||
|
|
||||||
|
int level = 0; |
||||||
|
int max = Math.Min(maxLevels - 3, stack.Count); |
||||||
|
|
||||||
|
while (level < max) |
||||||
|
{ |
||||||
|
WatchItem frame = stack[level]; |
||||||
|
|
||||||
|
string name = frame.Name; |
||||||
|
SourceRef sourceRef = frame.Location ?? DefaultSourceRef; |
||||||
|
int sourceIdx = sourceRef.SourceIdx; |
||||||
|
string path = sourceRef.IsClrLocation ? "(native)" : (m_Debug.GetSourceFile(sourceIdx) ?? "???"); |
||||||
|
string sourceName = Path.GetFileName(path); |
||||||
|
|
||||||
|
var source = new Source(sourceName, path); // ConvertDebuggerPathToClient(path)); |
||||||
|
|
||||||
|
stackFrames.Add(new StackFrame(level, name, source, |
||||||
|
ConvertDebuggerLineToClient(sourceRef.FromLine), sourceRef.FromChar, |
||||||
|
ConvertDebuggerLineToClient(sourceRef.ToLine), sourceRef.ToChar)); |
||||||
|
|
||||||
|
level++; |
||||||
|
} |
||||||
|
|
||||||
|
if (stack.Count > maxLevels - 3) |
||||||
|
stackFrames.Add(new StackFrame(level++, "(...)", null, 0)); |
||||||
|
|
||||||
|
if (coroutine != null) |
||||||
|
stackFrames.Add(new StackFrame(level++, "(" + coroutine.Name + ")", null, 0)); |
||||||
|
else |
||||||
|
stackFrames.Add(new StackFrame(level++, "(main coroutine)", null, 0)); |
||||||
|
|
||||||
|
stackFrames.Add(new StackFrame(level++, "(native)", null, 0)); |
||||||
|
|
||||||
|
SendResponse(response, new StackTraceResponseBody(stackFrames)); |
||||||
|
} |
||||||
|
|
||||||
|
readonly SourceRef DefaultSourceRef = new SourceRef(-1, 0, 0, 0, 0, false); |
||||||
|
|
||||||
|
|
||||||
|
private int getInt(Table args, string propName, int defaultValue) |
||||||
|
{ |
||||||
|
var jo = args.Get(propName); |
||||||
|
|
||||||
|
if (jo.Type != DataType.Number) |
||||||
|
return defaultValue; |
||||||
|
else |
||||||
|
return jo.ToObject<int>(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override void StepIn(Response response, Table arguments) |
||||||
|
{ |
||||||
|
m_Debug.QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepIn }); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void StepOut(Response response, Table arguments) |
||||||
|
{ |
||||||
|
m_Debug.QueueAction(new DebuggerAction() { Action = DebuggerAction.ActionType.StepOut }); |
||||||
|
SendResponse(response); |
||||||
|
} |
||||||
|
|
||||||
|
public override void Threads(Response response, Table arguments) |
||||||
|
{ |
||||||
|
var threads = new List<Thread>() { new Thread(0, "Main Thread") }; |
||||||
|
SendResponse(response, new ThreadsResponseBody(threads)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override void Variables(Response response, Table arguments) |
||||||
|
{ |
||||||
|
int index = getInt(arguments, "variablesReference", -1); |
||||||
|
|
||||||
|
var variables = new List<Variable>(); |
||||||
|
|
||||||
|
if (index == SCOPE_SELF) |
||||||
|
{ |
||||||
|
DynValue v = m_Debug.Evaluate("self"); |
||||||
|
VariableInspector.InspectVariable(v, variables); |
||||||
|
} |
||||||
|
else if (index == SCOPE_LOCALS) |
||||||
|
{ |
||||||
|
foreach (var w in m_Debug.GetWatches(WatchType.Locals)) |
||||||
|
variables.Add(new Variable(w.Name, (w.Value ?? DynValue.Void).ToDebugPrintString())); |
||||||
|
} |
||||||
|
else if (index < 0 || index >= m_Variables.Count) |
||||||
|
{ |
||||||
|
variables.Add(new Variable("<error>", null)); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
VariableInspector.InspectVariable(m_Variables[index], variables); |
||||||
|
} |
||||||
|
|
||||||
|
SendResponse(response, new VariablesResponseBody(variables)); |
||||||
|
} |
||||||
|
|
||||||
|
void IAsyncDebuggerClient.SendStopEvent() |
||||||
|
{ |
||||||
|
SendEvent(CreateStoppedEvent("step")); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void IAsyncDebuggerClient.OnWatchesUpdated(WatchType watchType) |
||||||
|
{ |
||||||
|
if (watchType == WatchType.CallStack) |
||||||
|
m_Variables.Clear(); |
||||||
|
} |
||||||
|
|
||||||
|
void IAsyncDebuggerClient.OnSourceCodeChanged(int sourceID) |
||||||
|
{ |
||||||
|
if (m_Debug.IsSourceOverride(sourceID)) |
||||||
|
SendText("Loaded source '{0}' -> '{1}'", m_Debug.GetSource(sourceID).Name, m_Debug.GetSourceFile(sourceID)); |
||||||
|
else |
||||||
|
SendText("Loaded source '{0}'", m_Debug.GetSource(sourceID).Name); |
||||||
|
} |
||||||
|
|
||||||
|
public void OnExecutionEnded() |
||||||
|
{ |
||||||
|
if (m_NotifyExecutionEnd) |
||||||
|
SendText("Execution ended."); |
||||||
|
} |
||||||
|
|
||||||
|
private void SendText(string msg, params object[] args) |
||||||
|
{ |
||||||
|
msg = string.Format(msg, args); |
||||||
|
// SendEvent(new OutputEvent("console", DateTime.Now.ToString("u") + ": " + msg + "\n")); |
||||||
|
SendEvent(new OutputEvent("console", msg + "\n")); |
||||||
|
} |
||||||
|
|
||||||
|
public void OnException(ScriptRuntimeException ex) |
||||||
|
{ |
||||||
|
SendText("runtime error : {0}", ex.DecoratedMessage); |
||||||
|
} |
||||||
|
|
||||||
|
public void Unbind() |
||||||
|
{ |
||||||
|
SendText("Debug session has been closed by the hosting process."); |
||||||
|
SendText("Bye."); |
||||||
|
SendEvent(new TerminatedEvent()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 8e5d177091ab64f8fbd15ad5f48d06ae |
||||||
|
timeCreated: 1476432884 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,88 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.VsCodeDebugger.SDK; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.DebuggerLogic |
||||||
|
{ |
||||||
|
internal static class VariableInspector |
||||||
|
{ |
||||||
|
internal static void InspectVariable(DynValue v, List<Variable> variables) |
||||||
|
{ |
||||||
|
variables.Add(new Variable("(value)", v.ToPrintString())); |
||||||
|
variables.Add(new Variable("(type)", v.Type.ToLuaDebuggerString())); |
||||||
|
variables.Add(new Variable("(val #id)", v.ReferenceID.ToString())); |
||||||
|
|
||||||
|
switch (v.Type) |
||||||
|
{ |
||||||
|
case DataType.Tuple: |
||||||
|
for (int i = 0; i < v.Tuple.Length; i++) |
||||||
|
variables.Add(new Variable("[i]", (v.Tuple[i] ?? DynValue.Void).ToDebugPrintString())); |
||||||
|
break; |
||||||
|
case DataType.Function: |
||||||
|
variables.Add(new Variable("(address)", v.Function.EntryPointByteCodeLocation.ToString("X8"))); |
||||||
|
variables.Add(new Variable("(upvalues)", v.Function.GetUpvaluesCount().ToString())); |
||||||
|
variables.Add(new Variable("(upvalues type)", v.Function.GetUpvaluesType().ToString())); |
||||||
|
break; |
||||||
|
case DataType.Table: |
||||||
|
|
||||||
|
if (v.Table.MetaTable != null && (v.Table.OwnerScript == null)) |
||||||
|
variables.Add(new Variable("(table type)", "prime table with metatable")); |
||||||
|
else if (v.Table.MetaTable != null) |
||||||
|
variables.Add(new Variable("(table type)", "has metatable")); |
||||||
|
else if (v.Table.OwnerScript == null) |
||||||
|
variables.Add(new Variable("(table type)", "prime table")); |
||||||
|
else |
||||||
|
variables.Add(new Variable("(table type)", "standard")); |
||||||
|
|
||||||
|
variables.Add(new Variable("(table #id)", v.Table.ReferenceID.ToString())); |
||||||
|
|
||||||
|
if (v.Table.MetaTable != null) |
||||||
|
variables.Add(new Variable("(metatable #id)", v.Table.MetaTable.ReferenceID.ToString())); |
||||||
|
|
||||||
|
variables.Add(new Variable("(length)", v.Table.Length.ToString())); |
||||||
|
|
||||||
|
foreach (TablePair p in v.Table.Pairs) |
||||||
|
variables.Add(new Variable("[" + p.Key.ToDebugPrintString() + "]", p.Value.ToDebugPrintString())); |
||||||
|
|
||||||
|
break; |
||||||
|
case DataType.UserData: |
||||||
|
if (v.UserData.Descriptor != null) |
||||||
|
{ |
||||||
|
variables.Add(new Variable("(descriptor)", v.UserData.Descriptor.Name)); |
||||||
|
variables.Add(new Variable("(native type)", v.UserData.Descriptor.Type.ToString())); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
variables.Add(new Variable("(descriptor)", "null!")); |
||||||
|
} |
||||||
|
|
||||||
|
variables.Add(new Variable("(native object)", v.UserData.Object != null ? v.UserData.Object.ToString() : "(null)")); |
||||||
|
break; |
||||||
|
case DataType.Thread: |
||||||
|
variables.Add(new Variable("(coroutine state)", v.Coroutine.State.ToString())); |
||||||
|
variables.Add(new Variable("(coroutine type)", v.Coroutine.Type.ToString())); |
||||||
|
variables.Add(new Variable("(auto-yield counter)", v.Coroutine.AutoYieldCounter.ToString())); |
||||||
|
break; |
||||||
|
case DataType.ClrFunction: |
||||||
|
variables.Add(new Variable("(name)", v.Callback.Name ?? "(unnamed)")); |
||||||
|
break; |
||||||
|
case DataType.TailCallRequest: |
||||||
|
case DataType.YieldRequest: |
||||||
|
case DataType.Nil: |
||||||
|
case DataType.Void: |
||||||
|
case DataType.Boolean: |
||||||
|
case DataType.Number: |
||||||
|
case DataType.String: |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 9b828a4315be6894f9ae25f9d3cacd0e |
||||||
|
timeCreated: 1476265158 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,399 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Net; |
||||||
|
using System.Net.Sockets; |
||||||
|
using System.Text; |
||||||
|
using System.Threading; |
||||||
|
using MoonSharp.VsCodeDebugger.DebuggerLogic; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.Interpreter.Debugging; |
||||||
|
using MoonSharp.VsCodeDebugger.SDK; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing a debugger allowing attaching from a Visual Studio Code debugging session. |
||||||
|
/// </summary> |
||||||
|
public class MoonSharpVsCodeDebugServer : IDisposable |
||||||
|
{ |
||||||
|
object m_Lock = new object(); |
||||||
|
List<AsyncDebugger> m_DebuggerList = new List<AsyncDebugger>(); |
||||||
|
AsyncDebugger m_Current = null; |
||||||
|
ManualResetEvent m_StopEvent = new ManualResetEvent(false); |
||||||
|
bool m_Started = false; |
||||||
|
int m_Port; |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of the <see cref="MoonSharpVsCodeDebugServer" /> class. |
||||||
|
/// </summary> |
||||||
|
/// <param name="port">The port on which the debugger listens. It's recommended to use 41912.</param> |
||||||
|
public MoonSharpVsCodeDebugServer(int port = 41912) |
||||||
|
{ |
||||||
|
m_Port = port; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Initializes a new instance of the <see cref="MoonSharpVsCodeDebugServer" /> class with a default script. |
||||||
|
/// Note that for this specific script, it will NOT attach the debugger to the script. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script object to debug.</param> |
||||||
|
/// <param name="port">The port on which the debugger listens. It's recommended to use 41912 unless you are going to keep more than one script object around.</param> |
||||||
|
/// <param name="sourceFinder">A function which gets in input a source code and returns the path to |
||||||
|
/// source file to use. It can return null and in that case (or if the file cannot be found) |
||||||
|
/// a temporary file will be generated on the fly.</param> |
||||||
|
[Obsolete("Use the constructor taking only a port, and the 'Attach' method instead.")] |
||||||
|
public MoonSharpVsCodeDebugServer(Script script, int port, Func<SourceCode, string> sourceFinder = null) |
||||||
|
{ |
||||||
|
m_Port = port; |
||||||
|
m_Current = new AsyncDebugger(script, sourceFinder ?? (s => s.Name), "Default script"); |
||||||
|
m_DebuggerList.Add(m_Current); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Attaches the specified script to the debugger |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="name">The name of the script.</param> |
||||||
|
/// <param name="sourceFinder">A function which gets in input a source code and returns the path to |
||||||
|
/// source file to use. It can return null and in that case (or if the file cannot be found) |
||||||
|
/// a temporary file will be generated on the fly.</param> |
||||||
|
/// <exception cref="ArgumentException">If the script has already been attached to this debugger.</exception> |
||||||
|
public void AttachToScript(Script script, string name, Func<SourceCode, string> sourceFinder = null) |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (m_DebuggerList.Any(d => d.Script == script)) |
||||||
|
throw new ArgumentException("Script already attached to this debugger."); |
||||||
|
|
||||||
|
var debugger = new AsyncDebugger(script, sourceFinder ?? (s => s.Name), name); |
||||||
|
script.AttachDebugger(debugger); |
||||||
|
m_DebuggerList.Add(debugger); |
||||||
|
|
||||||
|
if (m_Current == null) |
||||||
|
m_Current = debugger; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets a list of the attached debuggers by id and name |
||||||
|
/// </summary> |
||||||
|
public IEnumerable<KeyValuePair<int, string>> GetAttachedDebuggersByIdAndName() |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
return m_DebuggerList |
||||||
|
.OrderBy(d => d.Id) |
||||||
|
.Select(d => new KeyValuePair<int, string>(d.Id, d.Name)) |
||||||
|
.ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets or sets the current script by ID (see GetAttachedDebuggersByIdAndName). |
||||||
|
/// New vscode connections will attach to this debugger ID. Changing the current ID does NOT disconnect |
||||||
|
/// connected clients. |
||||||
|
/// </summary> |
||||||
|
public int? CurrentId |
||||||
|
{ |
||||||
|
get { lock (m_Lock) return m_Current != null ? m_Current.Id : (int?)null; } |
||||||
|
set |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (value == null) |
||||||
|
{ |
||||||
|
m_Current = null; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var current = (m_DebuggerList.FirstOrDefault(d => d.Id == value)); |
||||||
|
|
||||||
|
if (current == null) |
||||||
|
throw new ArgumentException("Cannot find debugger with given Id."); |
||||||
|
|
||||||
|
m_Current = current; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets or sets the current script. New vscode connections will attach to this script. Changing the current script does NOT disconnect |
||||||
|
/// connected clients. |
||||||
|
/// </summary> |
||||||
|
public Script Current |
||||||
|
{ |
||||||
|
get { lock(m_Lock) return m_Current != null ? m_Current.Script : null; } |
||||||
|
set |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (value == null) |
||||||
|
{ |
||||||
|
m_Current = null; |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
var current = (m_DebuggerList.FirstOrDefault(d => d.Script == value)); |
||||||
|
|
||||||
|
if (current == null) |
||||||
|
throw new ArgumentException("Cannot find debugger with given script associated."); |
||||||
|
|
||||||
|
m_Current = current; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Detaches the specified script. The debugger attached to that script will get disconnected. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <exception cref="ArgumentException">Thrown if the script cannot be found.</exception> |
||||||
|
public void Detach(Script script) |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
var removed = m_DebuggerList.FirstOrDefault(d => d.Script == script); |
||||||
|
|
||||||
|
if (removed == null) |
||||||
|
throw new ArgumentException("Cannot detach script - not found."); |
||||||
|
|
||||||
|
removed.Client = null; |
||||||
|
|
||||||
|
m_DebuggerList.Remove(removed); |
||||||
|
|
||||||
|
if (m_Current == removed) |
||||||
|
{ |
||||||
|
if (m_DebuggerList.Count > 0) |
||||||
|
m_Current = m_DebuggerList[m_DebuggerList.Count - 1]; |
||||||
|
else |
||||||
|
m_Current = null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets or sets a delegate which will be called when logging messages are generated |
||||||
|
/// </summary> |
||||||
|
public Action<string> Logger { get; set; } |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Gets the debugger object. Obsolete, use the new interface using the Attach method instead. |
||||||
|
/// </summary> |
||||||
|
[Obsolete("Use the Attach method instead.")] |
||||||
|
public IDebugger GetDebugger() |
||||||
|
{ |
||||||
|
lock(m_Lock) |
||||||
|
return m_Current; |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Stops listening |
||||||
|
/// </summary> |
||||||
|
/// <exception cref="InvalidOperationException">Cannot stop; server was not started.</exception> |
||||||
|
public void Dispose() |
||||||
|
{ |
||||||
|
m_StopEvent.Set(); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Starts listening on the localhost for incoming connections. |
||||||
|
/// </summary> |
||||||
|
public MoonSharpVsCodeDebugServer Start() |
||||||
|
{ |
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (m_Started) |
||||||
|
throw new InvalidOperationException("Cannot start; server has already been started."); |
||||||
|
|
||||||
|
m_StopEvent.Reset(); |
||||||
|
|
||||||
|
TcpListener serverSocket = null; |
||||||
|
serverSocket = new TcpListener(IPAddress.Parse("127.0.0.1"), m_Port); |
||||||
|
serverSocket.Start(); |
||||||
|
|
||||||
|
SpawnThread("VsCodeDebugServer_" + m_Port.ToString(), () => ListenThread(serverSocket)); |
||||||
|
|
||||||
|
m_Started = true; |
||||||
|
|
||||||
|
return this; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void ListenThread(TcpListener serverSocket) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
while (!m_StopEvent.WaitOne(0)) |
||||||
|
{ |
||||||
|
#if DOTNET_CORE |
||||||
|
var task = serverSocket.AcceptSocketAsync(); |
||||||
|
task.Wait(); |
||||||
|
var clientSocket = task.Result; |
||||||
|
#else |
||||||
|
var clientSocket = serverSocket.AcceptSocket(); |
||||||
|
#endif |
||||||
|
|
||||||
|
if (clientSocket != null) |
||||||
|
{ |
||||||
|
string sessionId = Guid.NewGuid().ToString("N"); |
||||||
|
Log("[{0}] : Accepted connection from client {1}", sessionId, clientSocket.RemoteEndPoint); |
||||||
|
|
||||||
|
SpawnThread("VsCodeDebugSession_" + sessionId, () => |
||||||
|
{ |
||||||
|
using (var networkStream = new NetworkStream(clientSocket)) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
RunSession(sessionId, networkStream); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
Log("[{0}] : Error : {1}", ex.Message); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#if DOTNET_CORE |
||||||
|
clientSocket.Dispose(); |
||||||
|
#else |
||||||
|
clientSocket.Close(); |
||||||
|
#endif |
||||||
|
Log("[{0}] : Client connection closed", sessionId); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
catch (Exception e) |
||||||
|
{ |
||||||
|
Log("Fatal error in listening thread : {0}", e.Message); |
||||||
|
} |
||||||
|
finally |
||||||
|
{ |
||||||
|
if (serverSocket != null) |
||||||
|
serverSocket.Stop(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void RunSession(string sessionId, NetworkStream stream) |
||||||
|
{ |
||||||
|
DebugSession debugSession = null; |
||||||
|
|
||||||
|
lock (m_Lock) |
||||||
|
{ |
||||||
|
if (m_Current != null) |
||||||
|
debugSession = new MoonSharpDebugSession(this, m_Current); |
||||||
|
else |
||||||
|
debugSession = new EmptyDebugSession(this); |
||||||
|
} |
||||||
|
|
||||||
|
debugSession.ProcessLoop(stream, stream); |
||||||
|
} |
||||||
|
|
||||||
|
private void Log(string format, params object[] args) |
||||||
|
{ |
||||||
|
Action<string> logger = Logger; |
||||||
|
|
||||||
|
if (logger != null) |
||||||
|
{ |
||||||
|
string msg = string.Format(format, args); |
||||||
|
logger(msg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static void SpawnThread(string name, Action threadProc) |
||||||
|
{ |
||||||
|
#if DOTNET_CORE |
||||||
|
System.Threading.Tasks.Task.Run(() => threadProc()); |
||||||
|
#else |
||||||
|
new System.Threading.Thread(() => threadProc()) |
||||||
|
{ |
||||||
|
IsBackground = true, |
||||||
|
Name = name |
||||||
|
} |
||||||
|
.Start(); |
||||||
|
#endif |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#else |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.Interpreter.Debugging; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger |
||||||
|
{ |
||||||
|
public class MoonSharpVsCodeDebugServer : IDisposable |
||||||
|
{ |
||||||
|
public MoonSharpVsCodeDebugServer(int port = 41912) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
[Obsolete("Use the constructor taking only a port, and the 'Attach' method instead.")] |
||||||
|
public MoonSharpVsCodeDebugServer(Script script, int port, Func<SourceCode, string> sourceFinder = null) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public void AttachToScript(Script script, string name, Func<SourceCode, string> sourceFinder = null) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public IEnumerable<KeyValuePair<int, string>> GetAttachedDebuggersByIdAndName() |
||||||
|
{ |
||||||
|
yield break; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public int? CurrentId |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
set { } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public Script Current |
||||||
|
{ |
||||||
|
get { return null; } |
||||||
|
set { } |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Detaches the specified script. The debugger attached to that script will get disconnected. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <exception cref="ArgumentException">Thrown if the script cannot be found.</exception> |
||||||
|
public void Detach(Script script) |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public Action<string> Logger { get; set; } |
||||||
|
|
||||||
|
|
||||||
|
[Obsolete("Use the Attach method instead.")] |
||||||
|
public IDebugger GetDebugger() |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public void Dispose() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public MoonSharpVsCodeDebugServer Start() |
||||||
|
{ |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1f49800a7463743149b597062d1b42a2 |
||||||
|
timeCreated: 1476432878 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: b0c4fed5fd89f42c5ba1250cd726961b |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,610 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------- |
||||||
|
Copyright (c) Microsoft Corporation |
||||||
|
|
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
MIT License |
||||||
|
|
||||||
|
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.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.IO; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.SDK |
||||||
|
{ |
||||||
|
// ---- Types ------------------------------------------------------------------------- |
||||||
|
|
||||||
|
public class Message |
||||||
|
{ |
||||||
|
public int id { get; private set; } |
||||||
|
public string format { get; private set; } |
||||||
|
public object variables { get; private set; } |
||||||
|
public object showUser { get; private set; } |
||||||
|
public object sendTelemetry { get; private set; } |
||||||
|
|
||||||
|
public Message(int id, string format, object variables = null, bool user = true, bool telemetry = false) |
||||||
|
{ |
||||||
|
this.id = id; |
||||||
|
this.format = format; |
||||||
|
this.variables = variables; |
||||||
|
this.showUser = user; |
||||||
|
this.sendTelemetry = telemetry; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class StackFrame |
||||||
|
{ |
||||||
|
public int id { get; private set; } |
||||||
|
public Source source { get; private set; } |
||||||
|
public int line { get; private set; } |
||||||
|
public int column { get; private set; } |
||||||
|
public string name { get; private set; } |
||||||
|
|
||||||
|
public int? endLine { get; private set; } |
||||||
|
public int? endColumn { get; private set; } |
||||||
|
|
||||||
|
public StackFrame(int id, string name, Source source, int line, int column = 0, int? endLine = null, int? endColumn = null) |
||||||
|
{ |
||||||
|
this.id = id; |
||||||
|
this.name = name; |
||||||
|
this.source = source; |
||||||
|
this.line = line; |
||||||
|
this.column = column; |
||||||
|
this.endLine = endLine; |
||||||
|
this.endColumn = endColumn; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Scope |
||||||
|
{ |
||||||
|
public string name { get; private set; } |
||||||
|
public int variablesReference { get; private set; } |
||||||
|
public bool expensive { get; private set; } |
||||||
|
|
||||||
|
public Scope(string name, int variablesReference, bool expensive = false) |
||||||
|
{ |
||||||
|
this.name = name; |
||||||
|
this.variablesReference = variablesReference; |
||||||
|
this.expensive = expensive; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Variable |
||||||
|
{ |
||||||
|
public string name { get; private set; } |
||||||
|
public string value { get; private set; } |
||||||
|
public int variablesReference { get; private set; } |
||||||
|
|
||||||
|
public Variable(string name, string value, int variablesReference = 0) |
||||||
|
{ |
||||||
|
this.name = name; |
||||||
|
this.value = value; |
||||||
|
this.variablesReference = variablesReference; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Thread |
||||||
|
{ |
||||||
|
public int id { get; private set; } |
||||||
|
public string name { get; private set; } |
||||||
|
|
||||||
|
public Thread(int id, string name) |
||||||
|
{ |
||||||
|
this.id = id; |
||||||
|
if (name == null || name.Length == 0) |
||||||
|
{ |
||||||
|
this.name = string.Format("Thread #{0}", id); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Source |
||||||
|
{ |
||||||
|
public string name { get; private set; } |
||||||
|
public string path { get; private set; } |
||||||
|
public int sourceReference { get; private set; } |
||||||
|
|
||||||
|
public Source(string name, string path, int sourceReference = 0) |
||||||
|
{ |
||||||
|
this.name = name; |
||||||
|
this.path = path; |
||||||
|
this.sourceReference = sourceReference; |
||||||
|
} |
||||||
|
|
||||||
|
public Source(string path, int sourceReference = 0) |
||||||
|
{ |
||||||
|
this.name = Path.GetFileName(path); |
||||||
|
this.path = path; |
||||||
|
this.sourceReference = sourceReference; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Breakpoint |
||||||
|
{ |
||||||
|
public bool verified { get; private set; } |
||||||
|
public int line { get; private set; } |
||||||
|
|
||||||
|
public Breakpoint(bool verified, int line) |
||||||
|
{ |
||||||
|
this.verified = verified; |
||||||
|
this.line = line; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ---- Events ------------------------------------------------------------------------- |
||||||
|
|
||||||
|
public class InitializedEvent : Event |
||||||
|
{ |
||||||
|
public InitializedEvent() |
||||||
|
: base("initialized") { } |
||||||
|
} |
||||||
|
|
||||||
|
public class StoppedEvent : Event |
||||||
|
{ |
||||||
|
public StoppedEvent(int tid, string reasn, string txt = null) |
||||||
|
: base("stopped", new |
||||||
|
{ |
||||||
|
threadId = tid, |
||||||
|
reason = reasn, |
||||||
|
text = txt |
||||||
|
}) |
||||||
|
{ } |
||||||
|
} |
||||||
|
|
||||||
|
public class ExitedEvent : Event |
||||||
|
{ |
||||||
|
public ExitedEvent(int exCode) |
||||||
|
: base("exited", new { exitCode = exCode }) { } |
||||||
|
} |
||||||
|
|
||||||
|
public class TerminatedEvent : Event |
||||||
|
{ |
||||||
|
public TerminatedEvent() |
||||||
|
: base("terminated") { } |
||||||
|
} |
||||||
|
|
||||||
|
public class ThreadEvent : Event |
||||||
|
{ |
||||||
|
public ThreadEvent(string reasn, int tid) |
||||||
|
: base("thread", new |
||||||
|
{ |
||||||
|
reason = reasn, |
||||||
|
threadId = tid |
||||||
|
}) |
||||||
|
{ } |
||||||
|
} |
||||||
|
|
||||||
|
public class OutputEvent : Event |
||||||
|
{ |
||||||
|
public OutputEvent(string cat, string outpt) |
||||||
|
: base("output", new |
||||||
|
{ |
||||||
|
category = cat, |
||||||
|
output = outpt |
||||||
|
}) |
||||||
|
{ } |
||||||
|
} |
||||||
|
|
||||||
|
// ---- Response ------------------------------------------------------------------------- |
||||||
|
|
||||||
|
public class Capabilities : ResponseBody |
||||||
|
{ |
||||||
|
|
||||||
|
public bool supportsConfigurationDoneRequest; |
||||||
|
public bool supportsFunctionBreakpoints; |
||||||
|
public bool supportsConditionalBreakpoints; |
||||||
|
public bool supportsEvaluateForHovers; |
||||||
|
public object[] exceptionBreakpointFilters; |
||||||
|
} |
||||||
|
|
||||||
|
public class ErrorResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
|
||||||
|
public Message error { get; private set; } |
||||||
|
|
||||||
|
public ErrorResponseBody(Message error) |
||||||
|
{ |
||||||
|
this.error = error; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class StackTraceResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
public StackFrame[] stackFrames { get; private set; } |
||||||
|
|
||||||
|
public StackTraceResponseBody(List<StackFrame> frames = null) |
||||||
|
{ |
||||||
|
if (frames == null) |
||||||
|
stackFrames = new StackFrame[0]; |
||||||
|
else |
||||||
|
stackFrames = frames.ToArray<StackFrame>(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class ScopesResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
public Scope[] scopes { get; private set; } |
||||||
|
|
||||||
|
public ScopesResponseBody(List<Scope> scps = null) |
||||||
|
{ |
||||||
|
if (scps == null) |
||||||
|
scopes = new Scope[0]; |
||||||
|
else |
||||||
|
scopes = scps.ToArray<Scope>(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class VariablesResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
public Variable[] variables { get; private set; } |
||||||
|
|
||||||
|
public VariablesResponseBody(List<Variable> vars = null) |
||||||
|
{ |
||||||
|
if (vars == null) |
||||||
|
variables = new Variable[0]; |
||||||
|
else |
||||||
|
variables = vars.ToArray<Variable>(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class ThreadsResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
public Thread[] threads { get; private set; } |
||||||
|
|
||||||
|
public ThreadsResponseBody(List<Thread> vars = null) |
||||||
|
{ |
||||||
|
if (vars == null) |
||||||
|
threads = new Thread[0]; |
||||||
|
else |
||||||
|
threads = vars.ToArray<Thread>(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class EvaluateResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
public string result { get; private set; } |
||||||
|
public string type { get; set; } |
||||||
|
public int variablesReference { get; private set; } |
||||||
|
|
||||||
|
public EvaluateResponseBody(string value, int reff = 0) |
||||||
|
{ |
||||||
|
result = value; |
||||||
|
variablesReference = reff; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class SetBreakpointsResponseBody : ResponseBody |
||||||
|
{ |
||||||
|
public Breakpoint[] breakpoints { get; private set; } |
||||||
|
|
||||||
|
public SetBreakpointsResponseBody(List<Breakpoint> bpts = null) |
||||||
|
{ |
||||||
|
if (bpts == null) |
||||||
|
breakpoints = new Breakpoint[0]; |
||||||
|
else |
||||||
|
breakpoints = bpts.ToArray<Breakpoint>(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// ---- The Session -------------------------------------------------------- |
||||||
|
|
||||||
|
public abstract class DebugSession : ProtocolServer |
||||||
|
{ |
||||||
|
private bool _debuggerLinesStartAt1; |
||||||
|
private bool _debuggerPathsAreURI; |
||||||
|
private bool _clientLinesStartAt1 = true; |
||||||
|
private bool _clientPathsAreURI = true; |
||||||
|
|
||||||
|
|
||||||
|
public DebugSession(bool debuggerLinesStartAt1, bool debuggerPathsAreURI = false) |
||||||
|
{ |
||||||
|
_debuggerLinesStartAt1 = debuggerLinesStartAt1; |
||||||
|
_debuggerPathsAreURI = debuggerPathsAreURI; |
||||||
|
} |
||||||
|
|
||||||
|
public void SendResponse(Response response, ResponseBody body = null) |
||||||
|
{ |
||||||
|
if (body != null) |
||||||
|
{ |
||||||
|
response.SetBody(body); |
||||||
|
} |
||||||
|
SendMessage(response); |
||||||
|
} |
||||||
|
|
||||||
|
public void SendErrorResponse(Response response, int id, string format, object arguments = null, bool user = true, bool telemetry = false) |
||||||
|
{ |
||||||
|
var msg = new Message(id, format, arguments, user, telemetry); |
||||||
|
var message = Utilities.ExpandVariables(msg.format, msg.variables); |
||||||
|
response.SetErrorBody(message, new ErrorResponseBody(msg)); |
||||||
|
SendMessage(response); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void DispatchRequest(string command, Table args, Response response) |
||||||
|
{ |
||||||
|
if (args == null) |
||||||
|
{ |
||||||
|
args = new Table(null); |
||||||
|
} |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
switch (command) |
||||||
|
{ |
||||||
|
|
||||||
|
case "initialize": |
||||||
|
|
||||||
|
if (args["linesStartAt1"] != null) |
||||||
|
_clientLinesStartAt1 = args.Get("linesStartAt1").ToObject<bool>(); |
||||||
|
|
||||||
|
var pathFormat = args.Get("pathFormat").ToObject<string>(); |
||||||
|
if (pathFormat != null) |
||||||
|
{ |
||||||
|
switch (pathFormat) |
||||||
|
{ |
||||||
|
case "uri": |
||||||
|
_clientPathsAreURI = true; |
||||||
|
break; |
||||||
|
case "path": |
||||||
|
_clientPathsAreURI = false; |
||||||
|
break; |
||||||
|
default: |
||||||
|
SendErrorResponse(response, 1015, "initialize: bad value '{_format}' for pathFormat", new { _format = pathFormat }); |
||||||
|
return; |
||||||
|
} |
||||||
|
} |
||||||
|
Initialize(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "launch": |
||||||
|
Launch(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "attach": |
||||||
|
Attach(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "disconnect": |
||||||
|
Disconnect(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "next": |
||||||
|
Next(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "continue": |
||||||
|
Continue(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "stepIn": |
||||||
|
StepIn(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "stepOut": |
||||||
|
StepOut(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "pause": |
||||||
|
Pause(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "stackTrace": |
||||||
|
StackTrace(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "scopes": |
||||||
|
Scopes(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "variables": |
||||||
|
Variables(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "source": |
||||||
|
Source(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "threads": |
||||||
|
Threads(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "setBreakpoints": |
||||||
|
SetBreakpoints(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "setFunctionBreakpoints": |
||||||
|
SetFunctionBreakpoints(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "setExceptionBreakpoints": |
||||||
|
SetExceptionBreakpoints(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
case "evaluate": |
||||||
|
Evaluate(response, args); |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
SendErrorResponse(response, 1014, "unrecognized request: {_request}", new { _request = command }); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
catch (Exception e) |
||||||
|
{ |
||||||
|
SendErrorResponse(response, 1104, "error while processing request '{_request}' (exception: {_exception})", new { _request = command, _exception = e.Message }); |
||||||
|
} |
||||||
|
|
||||||
|
if (command == "disconnect") |
||||||
|
{ |
||||||
|
Stop(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract void Initialize(Response response, Table args); |
||||||
|
|
||||||
|
public abstract void Launch(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Attach(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Disconnect(Response response, Table arguments); |
||||||
|
|
||||||
|
public virtual void SetFunctionBreakpoints(Response response, Table arguments) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public virtual void SetExceptionBreakpoints(Response response, Table arguments) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
public abstract void SetBreakpoints(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Continue(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Next(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void StepIn(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void StepOut(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Pause(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void StackTrace(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Scopes(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Variables(Response response, Table arguments); |
||||||
|
|
||||||
|
public virtual void Source(Response response, Table arguments) |
||||||
|
{ |
||||||
|
SendErrorResponse(response, 1020, "Source not supported"); |
||||||
|
} |
||||||
|
|
||||||
|
public abstract void Threads(Response response, Table arguments); |
||||||
|
|
||||||
|
public abstract void Evaluate(Response response, Table arguments); |
||||||
|
|
||||||
|
// protected |
||||||
|
|
||||||
|
protected int ConvertDebuggerLineToClient(int line) |
||||||
|
{ |
||||||
|
if (_debuggerLinesStartAt1) |
||||||
|
{ |
||||||
|
return _clientLinesStartAt1 ? line : line - 1; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return _clientLinesStartAt1 ? line + 1 : line; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected int ConvertClientLineToDebugger(int line) |
||||||
|
{ |
||||||
|
if (_debuggerLinesStartAt1) |
||||||
|
{ |
||||||
|
return _clientLinesStartAt1 ? line : line + 1; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return _clientLinesStartAt1 ? line - 1 : line; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected string ConvertDebuggerPathToClient(string path) |
||||||
|
{ |
||||||
|
if (_debuggerPathsAreURI) |
||||||
|
{ |
||||||
|
if (_clientPathsAreURI) |
||||||
|
{ |
||||||
|
return path; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
Uri uri = new Uri(path); |
||||||
|
return uri.LocalPath; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
if (_clientPathsAreURI) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
var uri = new System.Uri(path); |
||||||
|
return uri.AbsoluteUri; |
||||||
|
} |
||||||
|
catch |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return path; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected string ConvertClientPathToDebugger(string clientPath) |
||||||
|
{ |
||||||
|
if (clientPath == null) |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
if (_debuggerPathsAreURI) |
||||||
|
{ |
||||||
|
if (_clientPathsAreURI) |
||||||
|
{ |
||||||
|
return clientPath; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
var uri = new System.Uri(clientPath); |
||||||
|
return uri.AbsoluteUri; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
if (_clientPathsAreURI) |
||||||
|
{ |
||||||
|
if (Uri.IsWellFormedUriString(clientPath, UriKind.Absolute)) |
||||||
|
{ |
||||||
|
Uri uri = new Uri(clientPath); |
||||||
|
return uri.LocalPath; |
||||||
|
} |
||||||
|
Console.Error.WriteLine("path not well formed: '{0}'", clientPath); |
||||||
|
return null; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return clientPath; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 41359a96dff8e497abb39aab280e3dcf |
||||||
|
timeCreated: 1476265156 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,342 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------- |
||||||
|
Copyright (c) Microsoft Corporation |
||||||
|
|
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
MIT License |
||||||
|
|
||||||
|
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.Text; |
||||||
|
using System.IO; |
||||||
|
using System.Text.RegularExpressions; |
||||||
|
using MoonSharp.Interpreter; |
||||||
|
using MoonSharp.Interpreter.Serialization.Json; |
||||||
|
using MoonSharp.Interpreter.Serialization; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.SDK |
||||||
|
{ |
||||||
|
public class ProtocolMessage |
||||||
|
{ |
||||||
|
public int seq; |
||||||
|
public string type { get; private set; } |
||||||
|
|
||||||
|
public ProtocolMessage(string typ) |
||||||
|
{ |
||||||
|
type = typ; |
||||||
|
} |
||||||
|
|
||||||
|
public ProtocolMessage(string typ, int sq) |
||||||
|
{ |
||||||
|
type = typ; |
||||||
|
seq = sq; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Request : ProtocolMessage |
||||||
|
{ |
||||||
|
public string command; |
||||||
|
public Table arguments; |
||||||
|
|
||||||
|
public Request(int id, string cmd, Table arg) : base("request", id) |
||||||
|
{ |
||||||
|
command = cmd; |
||||||
|
arguments = arg; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
* subclasses of ResponseBody are serialized as the body of a response. |
||||||
|
* Don't change their instance variables since that will break the debug protocol. |
||||||
|
*/ |
||||||
|
public class ResponseBody |
||||||
|
{ |
||||||
|
// empty |
||||||
|
} |
||||||
|
|
||||||
|
public class Response : ProtocolMessage |
||||||
|
{ |
||||||
|
public bool success { get; private set; } |
||||||
|
public string message { get; private set; } |
||||||
|
public int request_seq { get; private set; } |
||||||
|
public string command { get; private set; } |
||||||
|
public ResponseBody body { get; private set; } |
||||||
|
|
||||||
|
public Response(Table req) : base("response") |
||||||
|
{ |
||||||
|
success = true; |
||||||
|
request_seq = req.Get("seq").ToObject<int>(); |
||||||
|
command = req.Get("command").ToObject<string>(); |
||||||
|
} |
||||||
|
|
||||||
|
public void SetBody(ResponseBody bdy) |
||||||
|
{ |
||||||
|
success = true; |
||||||
|
body = bdy; |
||||||
|
} |
||||||
|
|
||||||
|
public void SetErrorBody(string msg, ResponseBody bdy = null) |
||||||
|
{ |
||||||
|
success = false; |
||||||
|
message = msg; |
||||||
|
body = bdy; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public class Event : ProtocolMessage |
||||||
|
{ |
||||||
|
public string @event { get; private set; } |
||||||
|
public object body { get; private set; } |
||||||
|
|
||||||
|
public Event(string type, object bdy = null) : base("event") |
||||||
|
{ |
||||||
|
@event = type; |
||||||
|
body = bdy; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* |
||||||
|
* The ProtocolServer can be used to implement a server that uses the VSCode debug protocol. |
||||||
|
*/ |
||||||
|
public abstract class ProtocolServer |
||||||
|
{ |
||||||
|
public bool TRACE; |
||||||
|
public bool TRACE_RESPONSE; |
||||||
|
|
||||||
|
protected const int BUFFER_SIZE = 4096; |
||||||
|
protected const string TWO_CRLF = "\r\n\r\n"; |
||||||
|
protected static readonly Regex CONTENT_LENGTH_MATCHER = new Regex(@"Content-Length: (\d+)"); |
||||||
|
|
||||||
|
protected static readonly Encoding Encoding = System.Text.Encoding.UTF8; |
||||||
|
|
||||||
|
private int _sequenceNumber; |
||||||
|
|
||||||
|
private Stream _outputStream; |
||||||
|
|
||||||
|
private ByteBuffer _rawData; |
||||||
|
private int _bodyLength; |
||||||
|
|
||||||
|
private bool _stopRequested; |
||||||
|
|
||||||
|
|
||||||
|
public ProtocolServer() |
||||||
|
{ |
||||||
|
_sequenceNumber = 1; |
||||||
|
_bodyLength = -1; |
||||||
|
_rawData = new ByteBuffer(); |
||||||
|
} |
||||||
|
|
||||||
|
public void ProcessLoop(Stream inputStream, Stream outputStream) |
||||||
|
{ |
||||||
|
_outputStream = outputStream; |
||||||
|
|
||||||
|
byte[] buffer = new byte[BUFFER_SIZE]; |
||||||
|
|
||||||
|
_stopRequested = false; |
||||||
|
while (!_stopRequested) |
||||||
|
{ |
||||||
|
var read = inputStream.Read(buffer, 0, buffer.Length); |
||||||
|
|
||||||
|
if (read == 0) |
||||||
|
{ |
||||||
|
// end of stream |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
if (read > 0) |
||||||
|
{ |
||||||
|
_rawData.Append(buffer, read); |
||||||
|
ProcessData(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void Stop() |
||||||
|
{ |
||||||
|
_stopRequested = true; |
||||||
|
} |
||||||
|
|
||||||
|
public void SendEvent(Event e) |
||||||
|
{ |
||||||
|
SendMessage(e); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract void DispatchRequest(string command, Table args, Response response); |
||||||
|
|
||||||
|
// ---- private ------------------------------------------------------------------------ |
||||||
|
|
||||||
|
private void ProcessData() |
||||||
|
{ |
||||||
|
while (true) |
||||||
|
{ |
||||||
|
if (_bodyLength >= 0) |
||||||
|
{ |
||||||
|
if (_rawData.Length >= _bodyLength) |
||||||
|
{ |
||||||
|
var buf = _rawData.RemoveFirst(_bodyLength); |
||||||
|
|
||||||
|
_bodyLength = -1; |
||||||
|
|
||||||
|
Dispatch(Encoding.GetString(buf)); |
||||||
|
|
||||||
|
continue; // there may be more complete messages to process |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
string s = _rawData.GetString(Encoding); |
||||||
|
var idx = s.IndexOf(TWO_CRLF); |
||||||
|
if (idx != -1) |
||||||
|
{ |
||||||
|
Match m = CONTENT_LENGTH_MATCHER.Match(s); |
||||||
|
if (m.Success && m.Groups.Count == 2) |
||||||
|
{ |
||||||
|
_bodyLength = Convert.ToInt32(m.Groups[1].ToString()); |
||||||
|
|
||||||
|
_rawData.RemoveFirst(idx + TWO_CRLF.Length); |
||||||
|
|
||||||
|
continue; // try to handle a complete message |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void Dispatch(string req) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
Table request = JsonTableConverter.JsonToTable(req); |
||||||
|
if (request != null && request["type"].ToString() == "request") |
||||||
|
{ |
||||||
|
if (TRACE) |
||||||
|
Console.Error.WriteLine(string.Format("C {0}: {1}", request["command"], req)); |
||||||
|
|
||||||
|
var response = new Response(request); |
||||||
|
|
||||||
|
DispatchRequest(request.Get("command").String, request.Get("arguments").Table, response); |
||||||
|
|
||||||
|
SendMessage(response); |
||||||
|
} |
||||||
|
} |
||||||
|
catch |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected void SendMessage(ProtocolMessage message) |
||||||
|
{ |
||||||
|
message.seq = _sequenceNumber++; |
||||||
|
|
||||||
|
if (TRACE_RESPONSE && message.type == "response") |
||||||
|
{ |
||||||
|
Console.Error.WriteLine(string.Format(" R: {0}", JsonTableConverter.ObjectToJson(message))); |
||||||
|
} |
||||||
|
if (TRACE && message.type == "event") |
||||||
|
{ |
||||||
|
Event e = (Event)message; |
||||||
|
Console.Error.WriteLine(string.Format("E {0}: {1}", e.@event, JsonTableConverter.ObjectToJson(e.body))); |
||||||
|
} |
||||||
|
|
||||||
|
var data = ConvertToBytes(message); |
||||||
|
try |
||||||
|
{ |
||||||
|
_outputStream.Write(data, 0, data.Length); |
||||||
|
_outputStream.Flush(); |
||||||
|
} |
||||||
|
catch (Exception) |
||||||
|
{ |
||||||
|
// ignore |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static byte[] ConvertToBytes(ProtocolMessage request) |
||||||
|
{ |
||||||
|
var asJson = JsonTableConverter.ObjectToJson(request); |
||||||
|
byte[] jsonBytes = Encoding.GetBytes(asJson); |
||||||
|
|
||||||
|
string header = string.Format("Content-Length: {0}{1}", jsonBytes.Length, TWO_CRLF); |
||||||
|
byte[] headerBytes = Encoding.GetBytes(header); |
||||||
|
|
||||||
|
byte[] data = new byte[headerBytes.Length + jsonBytes.Length]; |
||||||
|
System.Buffer.BlockCopy(headerBytes, 0, data, 0, headerBytes.Length); |
||||||
|
System.Buffer.BlockCopy(jsonBytes, 0, data, headerBytes.Length, jsonBytes.Length); |
||||||
|
|
||||||
|
return data; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//-------------------------------------------------------------------------------------- |
||||||
|
|
||||||
|
class ByteBuffer |
||||||
|
{ |
||||||
|
private byte[] _buffer; |
||||||
|
|
||||||
|
public ByteBuffer() |
||||||
|
{ |
||||||
|
_buffer = new byte[0]; |
||||||
|
} |
||||||
|
|
||||||
|
public int Length |
||||||
|
{ |
||||||
|
get { return _buffer.Length; } |
||||||
|
} |
||||||
|
|
||||||
|
public string GetString(Encoding enc) |
||||||
|
{ |
||||||
|
return enc.GetString(_buffer); |
||||||
|
} |
||||||
|
|
||||||
|
public void Append(byte[] b, int length) |
||||||
|
{ |
||||||
|
byte[] newBuffer = new byte[_buffer.Length + length]; |
||||||
|
System.Buffer.BlockCopy(_buffer, 0, newBuffer, 0, _buffer.Length); |
||||||
|
System.Buffer.BlockCopy(b, 0, newBuffer, _buffer.Length, length); |
||||||
|
_buffer = newBuffer; |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] RemoveFirst(int n) |
||||||
|
{ |
||||||
|
byte[] b = new byte[n]; |
||||||
|
System.Buffer.BlockCopy(_buffer, 0, b, 0, n); |
||||||
|
byte[] newBuffer = new byte[_buffer.Length - n]; |
||||||
|
System.Buffer.BlockCopy(_buffer, n, newBuffer, 0, _buffer.Length - n); |
||||||
|
_buffer = newBuffer; |
||||||
|
return b; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 62430b596d436444d80bee2512f25a29 |
||||||
|
timeCreated: 1476265157 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,95 @@ |
|||||||
|
#if (!PCL) && ((!UNITY_5) || UNITY_STANDALONE) |
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------------------------- |
||||||
|
Copyright (c) Microsoft Corporation |
||||||
|
|
||||||
|
All rights reserved. |
||||||
|
|
||||||
|
MIT License |
||||||
|
|
||||||
|
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.Net; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Text.RegularExpressions; |
||||||
|
using System.Reflection; |
||||||
|
using MoonSharp.Interpreter.Compatibility; |
||||||
|
|
||||||
|
namespace MoonSharp.VsCodeDebugger.SDK |
||||||
|
{ |
||||||
|
internal class Utilities |
||||||
|
{ |
||||||
|
private static readonly Regex VARIABLE = new Regex(@"\{(\w+)\}"); |
||||||
|
|
||||||
|
|
||||||
|
/* |
||||||
|
* Resolve hostname, dotted-quad notation for IPv4, or colon-hexadecimal notation for IPv6 to IPAddress. |
||||||
|
* Returns null on failure. |
||||||
|
*/ |
||||||
|
|
||||||
|
public static string ExpandVariables(string format, object variables, bool underscoredOnly = true) |
||||||
|
{ |
||||||
|
if (variables == null) |
||||||
|
{ |
||||||
|
variables = new { }; |
||||||
|
} |
||||||
|
Type type = variables.GetType(); |
||||||
|
return VARIABLE.Replace(format, match => { |
||||||
|
string name = match.Groups[1].Value; |
||||||
|
if (!underscoredOnly || name.StartsWith("_")) |
||||||
|
{ |
||||||
|
|
||||||
|
PropertyInfo property = Framework.Do.GetProperty(type, name); |
||||||
|
if (property != null) |
||||||
|
{ |
||||||
|
object value = property.GetValue(variables, null); |
||||||
|
return value.ToString(); |
||||||
|
} |
||||||
|
return '{' + name + ": not found}"; |
||||||
|
} |
||||||
|
return match.Groups[0].Value; |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* converts the given absPath into a path that is relative to the given dirPath. |
||||||
|
*/ |
||||||
|
public static string MakeRelativePath(string dirPath, string absPath) |
||||||
|
{ |
||||||
|
if (!dirPath.EndsWith("/")) |
||||||
|
{ |
||||||
|
dirPath += "/"; |
||||||
|
} |
||||||
|
if (absPath.StartsWith(dirPath)) |
||||||
|
{ |
||||||
|
return absPath.Replace(dirPath, ""); |
||||||
|
} |
||||||
|
return absPath; |
||||||
|
/* |
||||||
|
Uri uri1 = new Uri(path); |
||||||
|
Uri uri2 = new Uri(dir_path); |
||||||
|
return uri2.MakeRelativeUri(uri1).ToString(); |
||||||
|
*/ |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 91853d42160014ebd843ee4e1a4f676e |
||||||
|
timeCreated: 1476432884 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1d2c5df22fca24da0aab88203047712f |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,421 @@ |
|||||||
|
#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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
public static class AsyncExtensions |
||||||
|
{ |
||||||
|
private static Task<T> ExecAsync<T>(Func<T> func) |
||||||
|
{ |
||||||
|
return Task.Factory.StartNew<T>(func); |
||||||
|
} |
||||||
|
|
||||||
|
private static Task ExecAsyncVoid(Action func) |
||||||
|
{ |
||||||
|
return Task.Factory.StartNew(func); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls this function with the specified args |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="function">The function.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Closure function) |
||||||
|
{ |
||||||
|
return ExecAsync(() => function.Call()); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls this function with the specified args |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="function">The function.</param> |
||||||
|
/// <param name="args">The arguments to pass to the function.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Closure function, params object[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => function.Call(args)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls this function with the specified args |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="function">The function.</param> |
||||||
|
/// <param name="args">The arguments to pass to the function.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Closure function, params DynValue[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => function.Call(args)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="code">The code.</param> |
||||||
|
/// <param name="globalContext">The global context.</param> |
||||||
|
/// <param name="codeFriendlyName">Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing the result of the processing of the loaded chunk. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> DoStringAsync(this Script script, string code, Table globalContext = null, string codeFriendlyName = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.DoString(code, globalContext, codeFriendlyName)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="stream">The stream.</param> |
||||||
|
/// <param name="globalContext">The global context.</param> |
||||||
|
/// <param name="codeFriendlyName">Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing the result of the processing of the loaded chunk. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> DoStreamAsync(this Script script, Stream stream, Table globalContext = null, string codeFriendlyName = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.DoStream(stream, globalContext, codeFriendlyName)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="filename">The filename.</param> |
||||||
|
/// <param name="globalContext">The global context.</param> |
||||||
|
/// <param name="codeFriendlyName">Name of the code - used to report errors, etc. Also used by debuggers to locate the original source file.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing the result of the processing of the loaded chunk. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> DoFileAsync(this Script script, string filename, Table globalContext = null, string codeFriendlyName = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.DoFile(filename, globalContext, codeFriendlyName)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously loads a string containing a Lua/MoonSharp function. |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="code">The code.</param> |
||||||
|
/// <param name="globalTable">The global table to bind to this chunk.</param> |
||||||
|
/// <param name="funcFriendlyName">Name of the function used to report errors, etc.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing a function which will execute the loaded code. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> LoadFunctionAsync(this Script script, string code, Table globalTable = null, string funcFriendlyName = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.LoadFunction(code, globalTable, funcFriendlyName)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously loads a string containing a Lua/MoonSharp script. |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="code">The code.</param> |
||||||
|
/// <param name="globalTable">The global table to bind to this chunk.</param> |
||||||
|
/// <param name="codeFriendlyName">Name of the code - used to report errors, etc.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing a function which will execute the loaded code. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> LoadStringAsync(this Script script, string code, Table globalTable = null, string codeFriendlyName = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.LoadString(code, globalTable, codeFriendlyName)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="stream">The stream containing code.</param> |
||||||
|
/// <param name="globalTable">The global table to bind to this chunk.</param> |
||||||
|
/// <param name="codeFriendlyName">Name of the code - used to report errors, etc.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing a function which will execute the loaded code. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> LoadStreamAsync(this Script script, Stream stream, Table globalTable = null, string codeFriendlyName = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.LoadStream(stream, globalTable, codeFriendlyName)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously dumps a function on the specified stream. |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="function">The function.</param> |
||||||
|
/// <param name="stream">The stream.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.ArgumentException">function arg is not a function! |
||||||
|
/// or |
||||||
|
/// stream is readonly! |
||||||
|
/// or |
||||||
|
/// function arg has upvalues other than _ENV</exception> |
||||||
|
public static Task DumpAsync(this Script script, DynValue function, Stream stream) |
||||||
|
{ |
||||||
|
return ExecAsyncVoid(() => script.Dump(function, stream)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously loads a string containing a Lua/MoonSharp script. |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="filename">The code.</param> |
||||||
|
/// <param name="globalContext">The global table to bind to this chunk.</param> |
||||||
|
/// <param name="friendlyFilename">The filename to be used in error messages.</param> |
||||||
|
/// <returns> |
||||||
|
/// A DynValue containing a function which will execute the loaded code. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> LoadFileAsync(this Script script, string filename, Table globalContext = null, string friendlyFilename = null) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.LoadFile(filename, globalContext, friendlyFilename)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Calls the specified function. |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="function">The Lua/MoonSharp function to be called</param> |
||||||
|
/// <returns> |
||||||
|
/// The return value(s) of the function call. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Script script, DynValue function) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.Call(function)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls the specified function. |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="function">The Lua/MoonSharp function to be called</param> |
||||||
|
/// <param name="args">The arguments to pass to the function.</param> |
||||||
|
/// <returns> |
||||||
|
/// The return value(s) of the function call. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Script script, DynValue function, params DynValue[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.Call(function, args)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls the specified function. |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="function">The Lua/MoonSharp function to be called</param> |
||||||
|
/// <param name="args">The arguments to pass to the function.</param> |
||||||
|
/// <returns> |
||||||
|
/// The return value(s) of the function call. |
||||||
|
/// </returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Script script, DynValue function, params object[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.Call(function, args)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls the specified function. |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="function">The Lua/MoonSharp function to be called</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Script script, object function) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.Call(function)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously calls the specified function. |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="function">The Lua/MoonSharp function to be called</param> |
||||||
|
/// <param name="args">The arguments to pass to the function.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.ArgumentException">Thrown if function is not of DataType.Function</exception> |
||||||
|
public static Task<DynValue> CallAsync(this Script script, object function, params object[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.Call(function, args)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Asynchronously creates a new dynamic expression. |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="script">The script.</param> |
||||||
|
/// <param name="code">The code of the expression.</param> |
||||||
|
/// <returns></returns> |
||||||
|
public static Task<DynamicExpression> CreateDynamicExpressionAsync(this Script script, string code) |
||||||
|
{ |
||||||
|
return ExecAsync(() => script.CreateDynamicExpression(code)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="interpreter">The interpreter.</param> |
||||||
|
/// <param name="input">The input.</param> |
||||||
|
/// <returns> |
||||||
|
/// This method returns the result of the computation, or null if more input is needed for a computation. |
||||||
|
/// </returns> |
||||||
|
public static Task<DynValue> EvaluateAsync(this ReplInterpreter interpreter, string input) |
||||||
|
{ |
||||||
|
return ExecAsync(() => interpreter.Evaluate(input)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="cor">The coroutine</param> |
||||||
|
/// <param name="args">The arguments.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.InvalidOperationException">Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead</exception> |
||||||
|
public static Task<DynValue> ResumeAsync(this Coroutine cor, params DynValue[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => cor.Resume(args)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Resumes the coroutine. |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="cor">The coroutine</param> |
||||||
|
/// <param name="context">The ScriptExecutionContext.</param> |
||||||
|
/// <param name="args">The arguments.</param> |
||||||
|
/// <returns></returns> |
||||||
|
public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params DynValue[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => cor.Resume(context, args)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="cor">The coroutine</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.InvalidOperationException">Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead</exception> |
||||||
|
public static Task<DynValue> ResumeAsync(this Coroutine cor) |
||||||
|
{ |
||||||
|
return ExecAsync(() => cor.Resume()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Resumes the coroutine. |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="cor">The coroutine</param> |
||||||
|
/// <param name="context">The ScriptExecutionContext.</param> |
||||||
|
/// <returns></returns> |
||||||
|
public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context) |
||||||
|
{ |
||||||
|
return ExecAsync(() => cor.Resume(context)); |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// 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. |
||||||
|
/// </summary> |
||||||
|
/// <param name="cor">The coroutine</param> |
||||||
|
/// <param name="args">The arguments.</param> |
||||||
|
/// <returns></returns> |
||||||
|
/// <exception cref="System.InvalidOperationException">Only non-CLR coroutines can be resumed with this overload of the Resume method. Use the overload accepting a ScriptExecutionContext instead.</exception> |
||||||
|
public static Task<DynValue> ResumeAsync(this Coroutine cor, params object[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => cor.Resume(args)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/// <summary> |
||||||
|
/// Resumes the coroutine |
||||||
|
/// |
||||||
|
/// This method is supported only on .NET 4.x and .NET 4.x PCL targets. |
||||||
|
/// </summary> |
||||||
|
/// <param name="cor">The coroutine</param> |
||||||
|
/// <param name="context">The ScriptExecutionContext.</param> |
||||||
|
/// <param name="args">The arguments.</param> |
||||||
|
/// <returns></returns> |
||||||
|
public static Task<DynValue> ResumeAsync(this Coroutine cor, ScriptExecutionContext context, params object[] args) |
||||||
|
{ |
||||||
|
return ExecAsync(() => cor.Resume(context, args)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 66aa67af332e348cbb7dd54b3d5d6433 |
||||||
|
timeCreated: 1475786654 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 5eef0a4b7d8c7458b9f013fcbe0202b3 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,7 @@ |
|||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CodeAnalysis |
||||||
|
{ |
||||||
|
class AstNode |
||||||
|
{ |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: db3e424c3ff444bb5b4872a8ecb430dd |
||||||
|
timeCreated: 1475786656 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -1,6 +1,7 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: 45b1b1eac93b04a4a8d6ec29d4803aa9 |
guid: 6d150008f68617545b69adb7e7fe0f28 |
||||||
timeCreated: 1454345352 |
folderAsset: yes |
||||||
|
timeCreated: 1476432865 |
||||||
licenseType: Free |
licenseType: Free |
||||||
DefaultImporter: |
DefaultImporter: |
||||||
userData: |
userData: |
@ -0,0 +1,21 @@ |
|||||||
|
#if PCL || ((!UNITY_EDITOR) && (ENABLE_DOTNET)) |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace System.Reflection |
||||||
|
{ |
||||||
|
internal class ComVisibleAttribute : Attribute |
||||||
|
{ |
||||||
|
public ComVisibleAttribute(bool dummy) |
||||||
|
{ } |
||||||
|
} |
||||||
|
internal class GuidAttribute : Attribute |
||||||
|
{ |
||||||
|
public GuidAttribute(string dummy) |
||||||
|
{ } |
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 24be313cbb7a91d42bb1de866ca88289 |
||||||
|
timeCreated: 1476432878 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,16 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter.Compatibility.Frameworks; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility |
||||||
|
{ |
||||||
|
public static class Framework |
||||||
|
{ |
||||||
|
static FrameworkCurrent s_FrameworkCurrent = new FrameworkCurrent(); |
||||||
|
|
||||||
|
public static FrameworkBase Do { get { return s_FrameworkCurrent; } } |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 96e3b35563b935d4c8baa02b06f40965 |
||||||
|
timeCreated: 1476432884 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -1,6 +1,7 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: 77bed9ffa87904128bf91eb0d73bd35e |
guid: 0d5353a4a6a04164095893dcf6dcd6cb |
||||||
timeCreated: 1455193522 |
folderAsset: yes |
||||||
|
timeCreated: 1476432866 |
||||||
licenseType: Free |
licenseType: Free |
||||||
DefaultImporter: |
DefaultImporter: |
||||||
userData: |
userData: |
@ -1,6 +1,7 @@ |
|||||||
fileFormatVersion: 2 |
fileFormatVersion: 2 |
||||||
guid: f5996939cde6945dbaa205884e73d770 |
guid: 0acf142145bc05446acafd786f0bac46 |
||||||
timeCreated: 1455193522 |
folderAsset: yes |
||||||
|
timeCreated: 1476432866 |
||||||
licenseType: Free |
licenseType: Free |
||||||
DefaultImporter: |
DefaultImporter: |
||||||
userData: |
userData: |
@ -0,0 +1,75 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
public abstract class FrameworkBase |
||||||
|
{ |
||||||
|
public abstract bool StringContainsChar(string str, char chr); |
||||||
|
|
||||||
|
public abstract bool IsValueType(Type t); |
||||||
|
|
||||||
|
public abstract Assembly GetAssembly(Type t); |
||||||
|
|
||||||
|
public abstract Type GetBaseType(Type t); |
||||||
|
|
||||||
|
public abstract bool IsGenericType(Type t); |
||||||
|
|
||||||
|
public abstract bool IsGenericTypeDefinition(Type t); |
||||||
|
|
||||||
|
public abstract bool IsEnum(Type t); |
||||||
|
|
||||||
|
public abstract bool IsNestedPublic(Type t); |
||||||
|
|
||||||
|
public abstract bool IsAbstract(Type t); |
||||||
|
|
||||||
|
public abstract bool IsInterface(Type t); |
||||||
|
|
||||||
|
public abstract Attribute[] GetCustomAttributes(Type t, bool inherit); |
||||||
|
|
||||||
|
public abstract Attribute[] GetCustomAttributes(Type t, Type at, bool inherit); |
||||||
|
|
||||||
|
public abstract Type[] GetInterfaces(Type t); |
||||||
|
|
||||||
|
public abstract bool IsInstanceOfType(Type t, object o); |
||||||
|
|
||||||
|
public abstract MethodInfo GetAddMethod(EventInfo ei); |
||||||
|
|
||||||
|
public abstract MethodInfo GetRemoveMethod(EventInfo ei); |
||||||
|
|
||||||
|
public abstract MethodInfo GetGetMethod(PropertyInfo pi); |
||||||
|
|
||||||
|
public abstract MethodInfo GetSetMethod(PropertyInfo pi); |
||||||
|
|
||||||
|
public abstract Type GetInterface(Type type, string name); |
||||||
|
|
||||||
|
public abstract PropertyInfo[] GetProperties(Type type); |
||||||
|
|
||||||
|
public abstract PropertyInfo GetProperty(Type type, string name); |
||||||
|
|
||||||
|
public abstract Type[] GetNestedTypes(Type type); |
||||||
|
|
||||||
|
public abstract EventInfo[] GetEvents(Type type); |
||||||
|
|
||||||
|
public abstract ConstructorInfo[] GetConstructors(Type type); |
||||||
|
|
||||||
|
public abstract Type[] GetAssemblyTypes(Assembly asm); |
||||||
|
|
||||||
|
public abstract MethodInfo[] GetMethods(Type type); |
||||||
|
|
||||||
|
public abstract FieldInfo[] GetFields(Type t); |
||||||
|
|
||||||
|
public abstract MethodInfo GetMethod(Type type, string name); |
||||||
|
|
||||||
|
public abstract Type[] GetGenericArguments(Type t); |
||||||
|
|
||||||
|
public abstract bool IsAssignableFrom(Type current, Type toCompare); |
||||||
|
|
||||||
|
public abstract bool IsDbNull(object o); |
||||||
|
|
||||||
|
public abstract MethodInfo GetMethod(Type resourcesType, string v, Type[] type); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: dbb9f51b6e0b0684ca09c843924edd61 |
||||||
|
timeCreated: 1476432886 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,116 @@ |
|||||||
|
#if !(DOTNET_CORE || NETFX_CORE) |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
abstract class FrameworkClrBase : FrameworkReflectionBase |
||||||
|
{ |
||||||
|
BindingFlags BINDINGFLAGS_MEMBER = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; |
||||||
|
BindingFlags BINDINGFLAGS_INNERCLASS = BindingFlags.Public | BindingFlags.NonPublic; |
||||||
|
|
||||||
|
public override Type GetTypeInfoFromType(Type t) |
||||||
|
{ |
||||||
|
return t; |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetAddMethod(EventInfo ei) |
||||||
|
{ |
||||||
|
return ei.GetAddMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
public override ConstructorInfo[] GetConstructors(Type type) |
||||||
|
{ |
||||||
|
return type.GetConstructors(BINDINGFLAGS_MEMBER); |
||||||
|
} |
||||||
|
|
||||||
|
public override EventInfo[] GetEvents(Type type) |
||||||
|
{ |
||||||
|
return type.GetEvents(BINDINGFLAGS_MEMBER); |
||||||
|
} |
||||||
|
|
||||||
|
public override FieldInfo[] GetFields(Type type) |
||||||
|
{ |
||||||
|
return type.GetFields(BINDINGFLAGS_MEMBER); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetGenericArguments(Type type) |
||||||
|
{ |
||||||
|
return type.GetGenericArguments(); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetGetMethod(PropertyInfo pi) |
||||||
|
{ |
||||||
|
return pi.GetGetMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetInterfaces(Type t) |
||||||
|
{ |
||||||
|
return t.GetInterfaces(); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetMethod(Type type, string name) |
||||||
|
{ |
||||||
|
return type.GetMethod(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo[] GetMethods(Type type) |
||||||
|
{ |
||||||
|
return type.GetMethods(BINDINGFLAGS_MEMBER); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetNestedTypes(Type type) |
||||||
|
{ |
||||||
|
return type.GetNestedTypes(BINDINGFLAGS_INNERCLASS); |
||||||
|
} |
||||||
|
|
||||||
|
public override PropertyInfo[] GetProperties(Type type) |
||||||
|
{ |
||||||
|
return type.GetProperties(BINDINGFLAGS_MEMBER); |
||||||
|
} |
||||||
|
|
||||||
|
public override PropertyInfo GetProperty(Type type, string name) |
||||||
|
{ |
||||||
|
return type.GetProperty(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetRemoveMethod(EventInfo ei) |
||||||
|
{ |
||||||
|
return ei.GetRemoveMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetSetMethod(PropertyInfo pi) |
||||||
|
{ |
||||||
|
return pi.GetSetMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override bool IsAssignableFrom(Type current, Type toCompare) |
||||||
|
{ |
||||||
|
return current.IsAssignableFrom(toCompare); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsInstanceOfType(Type t, object o) |
||||||
|
{ |
||||||
|
return t.IsInstanceOfType(o); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override MethodInfo GetMethod(Type resourcesType, string name, Type[] types) |
||||||
|
{ |
||||||
|
return resourcesType.GetMethod(name, types); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetAssemblyTypes(Assembly asm) |
||||||
|
{ |
||||||
|
return asm.GetTypes(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 0bbb9dec367acb94dbebde49d3745c4d |
||||||
|
timeCreated: 1476432876 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,76 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
#if DOTNET_CORE || NETFX_CORE |
||||||
|
using TTypeInfo = System.Reflection.TypeInfo; |
||||||
|
#else |
||||||
|
using TTypeInfo = System.Type; |
||||||
|
#endif |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
abstract class FrameworkReflectionBase : FrameworkBase |
||||||
|
{ |
||||||
|
public abstract TTypeInfo GetTypeInfoFromType(Type t); |
||||||
|
|
||||||
|
public override Assembly GetAssembly(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).Assembly; |
||||||
|
} |
||||||
|
|
||||||
|
public override Type GetBaseType(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).BaseType; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override bool IsValueType(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsValueType; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsInterface(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsInterface; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsNestedPublic(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsNestedPublic; |
||||||
|
} |
||||||
|
public override bool IsAbstract(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsAbstract; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsEnum(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsEnum; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsGenericTypeDefinition(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsGenericTypeDefinition; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsGenericType(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).IsGenericType; |
||||||
|
} |
||||||
|
|
||||||
|
public override Attribute[] GetCustomAttributes(Type t, bool inherit) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).GetCustomAttributes(inherit).OfType<Attribute>().ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
public override Attribute[] GetCustomAttributes(Type t, Type at, bool inherit) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).GetCustomAttributes(at, inherit).OfType<Attribute>().ToArray(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: f03cffebd263dcb4ab8680ce8d152968 |
||||||
|
timeCreated: 1476432887 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,31 @@ |
|||||||
|
#if !(DOTNET_CORE || NETFX_CORE) && !PCL |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
class FrameworkCurrent : FrameworkClrBase |
||||||
|
{ |
||||||
|
public override bool IsDbNull(object o) |
||||||
|
{ |
||||||
|
return o != null && Convert.IsDBNull(o); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override bool StringContainsChar(string str, char chr) |
||||||
|
{ |
||||||
|
return str.Contains(chr); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type GetInterface(Type type, string name) |
||||||
|
{ |
||||||
|
return type.GetInterface(name); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 25aeabf9258b9944ab81620030353790 |
||||||
|
timeCreated: 1476432878 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,132 @@ |
|||||||
|
#if DOTNET_CORE |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
class FrameworkCurrent : FrameworkReflectionBase |
||||||
|
{ |
||||||
|
public override TypeInfo GetTypeInfoFromType(Type t) |
||||||
|
{ |
||||||
|
return t.GetTypeInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
private T[] SafeArray<T>(IEnumerable<T> prop) |
||||||
|
{ |
||||||
|
return prop != null ? prop.ToArray() : new T[0]; |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetAddMethod(EventInfo ei) |
||||||
|
{ |
||||||
|
return ei.GetAddMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
public override ConstructorInfo[] GetConstructors(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredConstructors); |
||||||
|
} |
||||||
|
|
||||||
|
public override EventInfo[] GetEvents(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredEvents); |
||||||
|
} |
||||||
|
|
||||||
|
public override FieldInfo[] GetFields(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredFields); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetGenericArguments(Type type) |
||||||
|
{ |
||||||
|
return type.GetTypeInfo().GetGenericArguments(); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetGetMethod(PropertyInfo pi) |
||||||
|
{ |
||||||
|
return pi.GetGetMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type GetInterface(Type type, string name) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(type).GetInterface(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetInterfaces(Type t) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(t).GetInterfaces(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override MethodInfo GetMethod(Type type, string name) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(type).GetMethod(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo[] GetMethods(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredMethods); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetNestedTypes(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredNestedTypes.Select(ti => ti.AsType())); |
||||||
|
} |
||||||
|
|
||||||
|
public override PropertyInfo[] GetProperties(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredProperties); |
||||||
|
} |
||||||
|
|
||||||
|
public override PropertyInfo GetProperty(Type type, string name) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(type).GetProperty(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetRemoveMethod(EventInfo ei) |
||||||
|
{ |
||||||
|
return ei.GetRemoveMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetSetMethod(PropertyInfo pi) |
||||||
|
{ |
||||||
|
return pi.GetSetMethod(true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override bool IsAssignableFrom(Type current, Type toCompare) |
||||||
|
{ |
||||||
|
return current.GetTypeInfo().IsAssignableFrom(toCompare.GetTypeInfo()); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsDbNull(object o) |
||||||
|
{ |
||||||
|
return o != null && o.GetType().FullName.StartsWith("System.DBNull"); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsInstanceOfType(Type t, object o) |
||||||
|
{ |
||||||
|
return t.GetTypeInfo().IsInstanceOfType(o); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool StringContainsChar(string str, char chr) |
||||||
|
{ |
||||||
|
return str.Contains(chr); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetMethod(Type resourcesType, string name, Type[] types) |
||||||
|
{ |
||||||
|
return resourcesType.GetTypeInfo().GetMethod(name, types); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetAssemblyTypes(Assembly asm) |
||||||
|
{ |
||||||
|
return asm.GetExportedTypes(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: e6df3d0c4b051a347a75d7268c2f6d2a |
||||||
|
timeCreated: 1476432886 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,30 @@ |
|||||||
|
#if !(DOTNET_CORE || NETFX_CORE) && PCL |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
class FrameworkCurrent : FrameworkClrBase |
||||||
|
{ |
||||||
|
public override bool IsDbNull(object o) |
||||||
|
{ |
||||||
|
return o != null && o.GetType().FullName.StartsWith("System.DBNull"); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool StringContainsChar(string str, char chr) |
||||||
|
{ |
||||||
|
return str.Contains(chr.ToString()); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type GetInterface(Type type, string name) |
||||||
|
{ |
||||||
|
return type.GetInterfaces(). |
||||||
|
FirstOrDefault(t => t.Name == name); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: bac0f6f9dc5d85f41af33f3b83dbee01 |
||||||
|
timeCreated: 1476432885 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,160 @@ |
|||||||
|
#if NETFX_CORE && !DOTNET_CORE |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Reflection; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.Compatibility.Frameworks |
||||||
|
{ |
||||||
|
class FrameworkCurrent : FrameworkReflectionBase |
||||||
|
{ |
||||||
|
public override TypeInfo GetTypeInfoFromType(Type t) |
||||||
|
{ |
||||||
|
return t.GetTypeInfo(); |
||||||
|
} |
||||||
|
|
||||||
|
private T[] SafeArray<T>(IEnumerable<T> prop) |
||||||
|
{ |
||||||
|
return prop != null ? prop.ToArray() : new T[0]; |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetAddMethod(EventInfo ei) |
||||||
|
{ |
||||||
|
return ei.AddMethod; |
||||||
|
} |
||||||
|
|
||||||
|
public override ConstructorInfo[] GetConstructors(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredConstructors); |
||||||
|
} |
||||||
|
|
||||||
|
public override EventInfo[] GetEvents(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredEvents); |
||||||
|
} |
||||||
|
|
||||||
|
public override FieldInfo[] GetFields(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredFields); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetGenericArguments(Type type) |
||||||
|
{ |
||||||
|
return type.GetTypeInfo().GenericTypeArguments; |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetGetMethod(PropertyInfo pi) |
||||||
|
{ |
||||||
|
return pi.GetMethod; |
||||||
|
} |
||||||
|
|
||||||
|
public override Type GetInterface(Type type, string name) |
||||||
|
{ |
||||||
|
return type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault(t => t.Name == name); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetInterfaces(Type t) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(t).ImplementedInterfaces); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override MethodInfo GetMethod(Type type, string name) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(type).GetDeclaredMethod(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo[] GetMethods(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredMethods); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetNestedTypes(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredNestedTypes.Select(ti => ti.AsType())); |
||||||
|
} |
||||||
|
|
||||||
|
public override PropertyInfo[] GetProperties(Type type) |
||||||
|
{ |
||||||
|
return SafeArray(GetTypeInfoFromType(type).DeclaredProperties); |
||||||
|
} |
||||||
|
|
||||||
|
public override PropertyInfo GetProperty(Type type, string name) |
||||||
|
{ |
||||||
|
return GetTypeInfoFromType(type).GetDeclaredProperty(name); |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetRemoveMethod(EventInfo ei) |
||||||
|
{ |
||||||
|
return ei.RemoveMethod; |
||||||
|
} |
||||||
|
|
||||||
|
public override MethodInfo GetSetMethod(PropertyInfo pi) |
||||||
|
{ |
||||||
|
return pi.SetMethod; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override bool IsAssignableFrom(Type current, Type toCompare) |
||||||
|
{ |
||||||
|
return current.GetTypeInfo().IsAssignableFrom(toCompare.GetTypeInfo()); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsDbNull(object o) |
||||||
|
{ |
||||||
|
return o != null && o.GetType().FullName.StartsWith("System.DBNull"); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool IsInstanceOfType(Type t, object o) |
||||||
|
{ |
||||||
|
if (o == null) |
||||||
|
return false; |
||||||
|
|
||||||
|
return t.GetTypeInfo().IsAssignableFrom(o.GetType().GetTypeInfo()); |
||||||
|
} |
||||||
|
|
||||||
|
public override bool StringContainsChar(string str, char chr) |
||||||
|
{ |
||||||
|
return str.Contains(chr); |
||||||
|
} |
||||||
|
|
||||||
|
private static MethodInfo GetMethodEx(Type t, string name, Type[] parameters) |
||||||
|
{ |
||||||
|
var ti = t.GetTypeInfo(); |
||||||
|
var methods = ti.GetDeclaredMethods(name); |
||||||
|
foreach (var m in methods) |
||||||
|
{ |
||||||
|
var plist = m.GetParameters(); |
||||||
|
bool match = true; |
||||||
|
foreach (var param in plist) |
||||||
|
{ |
||||||
|
bool valid = true; |
||||||
|
if (parameters != null) |
||||||
|
{ |
||||||
|
foreach (var ptype in parameters) |
||||||
|
valid &= ptype == param.ParameterType; |
||||||
|
} |
||||||
|
match &= valid; |
||||||
|
} |
||||||
|
if (match) |
||||||
|
return m; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public override MethodInfo GetMethod(Type resourcesType, string name, Type[] types) |
||||||
|
{ |
||||||
|
return GetMethodEx(resourcesType, name, types); |
||||||
|
} |
||||||
|
|
||||||
|
public override Type[] GetAssemblyTypes(Assembly asm) |
||||||
|
{ |
||||||
|
return SafeArray(asm.ExportedTypes); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 11ab1e37f96fc08418f4794c17e8be0c |
||||||
|
timeCreated: 1476435850 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,41 @@ |
|||||||
|
#if PCL || ((!UNITY_EDITOR) && (ENABLE_DOTNET)) |
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace System.Diagnostics |
||||||
|
{ |
||||||
|
internal class Stopwatch |
||||||
|
{ |
||||||
|
DateTime startTime, stopTime; |
||||||
|
|
||||||
|
public void Start() |
||||||
|
{ |
||||||
|
startTime = DateTime.UtcNow; |
||||||
|
} |
||||||
|
|
||||||
|
public void Stop() |
||||||
|
{ |
||||||
|
stopTime = DateTime.UtcNow; |
||||||
|
} |
||||||
|
|
||||||
|
public static Stopwatch StartNew() |
||||||
|
{ |
||||||
|
Stopwatch sw = new Stopwatch(); |
||||||
|
sw.Start(); |
||||||
|
return sw; |
||||||
|
} |
||||||
|
|
||||||
|
public long ElapsedMilliseconds |
||||||
|
{ |
||||||
|
get |
||||||
|
{ |
||||||
|
return (long)((stopTime - startTime).TotalMilliseconds); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
#endif |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 23ea8da0a506c1444af1949fa30dd149 |
||||||
|
timeCreated: 1476432878 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 960b24834b8044fc6acf64f473b5ca61 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,273 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Globalization; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing basic Lua functions (print, type, tostring, etc) as a MoonSharp module. |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule] |
||||||
|
public class BasicModule |
||||||
|
{ |
||||||
|
//type (v) |
||||||
|
//---------------------------------------------------------------------------------------------------------------- |
||||||
|
//Returns the type of its only argument, coded as a string. The possible results of this function are "nil" |
||||||
|
//(a string, not the value nil), "number", "string", "boolean", "table", "function", "thread", and "userdata". |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue type(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args.Count < 1) throw ScriptRuntimeException.BadArgumentValueExpected(0, "type"); |
||||||
|
|
||||||
|
DynValue v = args[0]; |
||||||
|
return DynValue.NewString(v.Type.ToLuaTypeString()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//assert (v [, message]) |
||||||
|
//---------------------------------------------------------------------------------------------------------------- |
||||||
|
//Issues an error when the value of its argument v is false (i.e., nil or false); |
||||||
|
//otherwise, returns all its arguments. message is an error message; when absent, it defaults to "assertion failed!" |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue assert(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v = args[0]; |
||||||
|
DynValue message = args[1]; |
||||||
|
|
||||||
|
if (!v.CastToBool()) |
||||||
|
{ |
||||||
|
if (message.IsNil()) |
||||||
|
throw new ScriptRuntimeException("assertion failed!"); // { DoNotDecorateMessage = true }; |
||||||
|
else |
||||||
|
throw new ScriptRuntimeException(message.ToPrintString()); // { DoNotDecorateMessage = true }; |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewTupleNested(args.GetArray()); |
||||||
|
} |
||||||
|
|
||||||
|
// collectgarbage ([opt [, arg]]) |
||||||
|
// ---------------------------------------------------------------------------------------------------------------- |
||||||
|
// This function is mostly a stub towards the CLR GC. If mode is nil, "collect" or "restart", a GC is forced. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue collectgarbage(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue opt = args[0]; |
||||||
|
|
||||||
|
string mode = opt.CastToString(); |
||||||
|
|
||||||
|
if (mode == null || mode == "collect" || mode == "restart") |
||||||
|
{ |
||||||
|
#if PCL || ENABLE_DOTNET |
||||||
|
GC.Collect(); |
||||||
|
#else |
||||||
|
GC.Collect(2, GCCollectionMode.Forced); |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
|
||||||
|
// error (message [, level]) |
||||||
|
// ---------------------------------------------------------------------------------------------------------------- |
||||||
|
// Terminates the last protected function called and returns message as the error message. Function error never returns. |
||||||
|
// Usually, error adds some information about the error position at the beginning of the message. |
||||||
|
// The level argument specifies how to get the error position. |
||||||
|
// With level 1 (the default), the error position is where the error function was called. |
||||||
|
// Level 2 points the error to where the function that called error was called; and so on. |
||||||
|
// Passing a level 0 avoids the addition of error position information to the message. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue error(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue message = args.AsType(0, "error", DataType.String, false); |
||||||
|
throw new ScriptRuntimeException(message.String); // { DoNotDecorateMessage = true }; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// tostring (v) |
||||||
|
// ---------------------------------------------------------------------------------------------------------------- |
||||||
|
// Receives a value of any type and converts it to a string in a reasonable format. (For complete control of how |
||||||
|
// numbers are converted, use string.format.) |
||||||
|
// |
||||||
|
// If the metatable of v has a "__tostring" field, then tostring calls the corresponding value with v as argument, |
||||||
|
// and uses the result of the call as its result. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue tostring(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args.Count < 1) throw ScriptRuntimeException.BadArgumentValueExpected(0, "tostring"); |
||||||
|
|
||||||
|
DynValue v = args[0]; |
||||||
|
DynValue tail = executionContext.GetMetamethodTailCall(v, "__tostring", v); |
||||||
|
|
||||||
|
if (tail == null || tail.IsNil()) |
||||||
|
return DynValue.NewString(v.ToPrintString()); |
||||||
|
|
||||||
|
tail.TailCallData.Continuation = new CallbackFunction(__tostring_continuation, "__tostring"); |
||||||
|
|
||||||
|
return tail; |
||||||
|
} |
||||||
|
|
||||||
|
private static DynValue __tostring_continuation(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue b = args[0].ToScalar(); |
||||||
|
|
||||||
|
if (b.IsNil()) |
||||||
|
return b; |
||||||
|
|
||||||
|
if (b.Type != DataType.String) |
||||||
|
throw new ScriptRuntimeException("'tostring' must return a string"); |
||||||
|
|
||||||
|
|
||||||
|
return b; |
||||||
|
} |
||||||
|
|
||||||
|
// select (index, ...) |
||||||
|
// ----------------------------------------------------------------------------- |
||||||
|
// If index is a number, returns all arguments after argument number index; a negative number indexes from |
||||||
|
// the end (-1 is the last argument). Otherwise, index must be the string "#", and select returns the total |
||||||
|
// number of extra arguments it received. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue select(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args[0].Type == DataType.String && args[0].String == "#") |
||||||
|
{ |
||||||
|
if (args[args.Count - 1].Type == DataType.Tuple) |
||||||
|
{ |
||||||
|
return DynValue.NewNumber(args.Count - 1 + args[args.Count - 1].Tuple.Length); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return DynValue.NewNumber(args.Count - 1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
DynValue v_num = args.AsType(0, "select", DataType.Number, false); |
||||||
|
int num = (int)v_num.Number; |
||||||
|
|
||||||
|
List<DynValue> values = new List<DynValue>(); |
||||||
|
|
||||||
|
if (num > 0) |
||||||
|
{ |
||||||
|
for (int i = num; i < args.Count; i++) |
||||||
|
values.Add(args[i]); |
||||||
|
} |
||||||
|
else if (num < 0) |
||||||
|
{ |
||||||
|
num = args.Count + num; |
||||||
|
|
||||||
|
if (num < 1) |
||||||
|
throw ScriptRuntimeException.BadArgumentIndexOutOfRange("select", 0); |
||||||
|
|
||||||
|
for (int i = num; i < args.Count; i++) |
||||||
|
values.Add(args[i]); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw ScriptRuntimeException.BadArgumentIndexOutOfRange("select", 0); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewTupleNested(values.ToArray()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// tonumber (e [, base]) |
||||||
|
// ---------------------------------------------------------------------------------------------------------------- |
||||||
|
// When called with no base, tonumber tries to convert its argument to a number. If the argument is already |
||||||
|
// a number or a string convertible to a number (see §3.4.2), then tonumber returns this number; otherwise, |
||||||
|
// it returns nil. |
||||||
|
// |
||||||
|
// When called with base, then e should be a string to be interpreted as an integer numeral in that base. |
||||||
|
// The base may be any integer between 2 and 36, inclusive. In bases above 10, the letter 'A' (in either |
||||||
|
// upper or lower case) represents 10, 'B' represents 11, and so forth, with 'Z' representing 35. If the |
||||||
|
// string e is not a valid numeral in the given base, the function returns nil. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue tonumber(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args.Count < 1) throw ScriptRuntimeException.BadArgumentValueExpected(0, "tonumber"); |
||||||
|
|
||||||
|
DynValue e = args[0]; |
||||||
|
DynValue b = args.AsType(1, "tonumber", DataType.Number, true); |
||||||
|
|
||||||
|
if (b.IsNil()) |
||||||
|
{ |
||||||
|
if (e.Type == DataType.Number) |
||||||
|
return e; |
||||||
|
|
||||||
|
if (e.Type != DataType.String) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
double d; |
||||||
|
if (double.TryParse(e.String, NumberStyles.Any, CultureInfo.InvariantCulture, out d)) |
||||||
|
{ |
||||||
|
return DynValue.NewNumber(d); |
||||||
|
} |
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
//!COMPAT: tonumber supports only 2,8,10 or 16 as base |
||||||
|
//UPDATE: added support for 3-9 base numbers |
||||||
|
DynValue ee; |
||||||
|
|
||||||
|
if (args[0].Type != DataType.Number) |
||||||
|
ee = args.AsType(0, "tonumber", DataType.String, false); |
||||||
|
else |
||||||
|
ee = DynValue.NewString(args[0].Number.ToString(CultureInfo.InvariantCulture)); ; |
||||||
|
|
||||||
|
int bb = (int)b.Number; |
||||||
|
|
||||||
|
uint uiv = 0; |
||||||
|
if (bb == 2 || bb == 8 || bb == 10 || bb == 16) |
||||||
|
{ |
||||||
|
uiv = Convert.ToUInt32(ee.String.Trim(), bb); |
||||||
|
} |
||||||
|
else if (bb < 10 && bb > 2) // Support for 3, 4, 5, 6, 7 and 9 based numbers |
||||||
|
{ |
||||||
|
foreach (char digit in ee.String.Trim()) |
||||||
|
{ |
||||||
|
int value = digit - 48; |
||||||
|
if (value < 0 || value >= bb) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException("bad argument #1 to 'tonumber' (invalid character)"); |
||||||
|
} |
||||||
|
|
||||||
|
uiv = (uint)(uiv * bb) + (uint)value; |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException("bad argument #2 to 'tonumber' (base out of range)"); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewNumber(uiv); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue print(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
|
||||||
|
for (int i = 0; i < args.Count; i++) |
||||||
|
{ |
||||||
|
if (args[i].IsVoid()) |
||||||
|
break; |
||||||
|
|
||||||
|
if (i != 0) |
||||||
|
sb.Append('\t'); |
||||||
|
|
||||||
|
sb.Append(args.AsStringUsingMeta(executionContext, i, "print")); |
||||||
|
} |
||||||
|
|
||||||
|
executionContext.GetScript().Options.DebugPrint(sb.ToString()); |
||||||
|
|
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: eed70b0c3561d4512b8cf9426b5814cd |
||||||
|
timeCreated: 1476205335 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,245 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing bit32 Lua functions |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "bit32")] |
||||||
|
public class Bit32Module |
||||||
|
{ |
||||||
|
static readonly uint[] MASKS = new uint[] { |
||||||
|
0x1, 0x3, 0x7, 0xF, |
||||||
|
0x1F, 0x3F, 0x7F, 0xFF, |
||||||
|
0x1FF, 0x3FF, 0x7FF, 0xFFF, |
||||||
|
0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, |
||||||
|
0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, |
||||||
|
0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, |
||||||
|
0x1FFFFFF, 0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, |
||||||
|
0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF, }; |
||||||
|
|
||||||
|
static uint ToUInt32(DynValue v) |
||||||
|
{ |
||||||
|
double d = v.Number; |
||||||
|
d = Math.IEEERemainder(d, Math.Pow(2.0, 32.0)); |
||||||
|
return (uint)d; |
||||||
|
} |
||||||
|
|
||||||
|
static int ToInt32(DynValue v) |
||||||
|
{ |
||||||
|
double d = v.Number; |
||||||
|
d = Math.IEEERemainder(d, Math.Pow(2.0, 32.0)); |
||||||
|
return (int)d; |
||||||
|
} |
||||||
|
|
||||||
|
static uint NBitMask(int bits) |
||||||
|
{ |
||||||
|
|
||||||
|
if (bits <= 0) |
||||||
|
return 0; |
||||||
|
if (bits >= 32) |
||||||
|
return MASKS[31]; |
||||||
|
|
||||||
|
return MASKS[bits - 1]; |
||||||
|
} |
||||||
|
|
||||||
|
public static uint Bitwise(string funcName, CallbackArguments args, Func<uint, uint, uint> accumFunc) |
||||||
|
{ |
||||||
|
uint accum = ToUInt32(args.AsType(0, funcName, DataType.Number, false)); |
||||||
|
|
||||||
|
for (int i = 1; i < args.Count; i++) |
||||||
|
{ |
||||||
|
uint vv = ToUInt32(args.AsType(i, funcName, DataType.Number, false)); |
||||||
|
accum = accumFunc(accum, vv); |
||||||
|
} |
||||||
|
|
||||||
|
return accum; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue extract(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "extract", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_pos = args.AsType(1, "extract", DataType.Number); |
||||||
|
DynValue v_width = args.AsType(2, "extract", DataType.Number, true); |
||||||
|
|
||||||
|
int pos = (int)v_pos.Number; |
||||||
|
int width = (v_width).IsNilOrNan() ? 1 : (int)v_width.Number; |
||||||
|
|
||||||
|
ValidatePosWidth("extract", 2, pos, width); |
||||||
|
|
||||||
|
uint res = (v >> pos) & NBitMask(width); |
||||||
|
return DynValue.NewNumber(res); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue replace(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "replace", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_u = args.AsType(1, "replace", DataType.Number); |
||||||
|
uint u = ToUInt32(v_u); |
||||||
|
DynValue v_pos = args.AsType(2, "replace", DataType.Number); |
||||||
|
DynValue v_width = args.AsType(3, "replace", DataType.Number, true); |
||||||
|
|
||||||
|
int pos = (int)v_pos.Number; |
||||||
|
int width = (v_width).IsNilOrNan() ? 1 : (int)v_width.Number; |
||||||
|
|
||||||
|
ValidatePosWidth("replace", 3, pos, width); |
||||||
|
|
||||||
|
uint mask = NBitMask(width) << pos; |
||||||
|
v = v & (~mask); |
||||||
|
u = u & (mask); |
||||||
|
v = v | u; |
||||||
|
|
||||||
|
return DynValue.NewNumber(v); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static void ValidatePosWidth(string func, int argPos, int pos, int width) |
||||||
|
{ |
||||||
|
if (pos > 31 || (pos + width) > 31) |
||||||
|
throw new ScriptRuntimeException("trying to access non-existent bits"); |
||||||
|
|
||||||
|
if (pos < 0) |
||||||
|
throw new ScriptRuntimeException("bad argument #{1} to '{0}' (field cannot be negative)", func, argPos); |
||||||
|
|
||||||
|
if (width <= 0) |
||||||
|
throw new ScriptRuntimeException("bad argument #{1} to '{0}' (width must be positive)", func, argPos+1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue arshift(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "arshift", DataType.Number); |
||||||
|
int v = ToInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_a = args.AsType(1, "arshift", DataType.Number); |
||||||
|
|
||||||
|
int a = (int)v_a.Number; |
||||||
|
|
||||||
|
if (a < 0) |
||||||
|
v = v << -a; |
||||||
|
else |
||||||
|
v = v >> a; |
||||||
|
|
||||||
|
return DynValue.NewNumber(v); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rshift(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "rshift", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_a = args.AsType(1, "rshift", DataType.Number); |
||||||
|
|
||||||
|
int a = (int)v_a.Number; |
||||||
|
|
||||||
|
if (a < 0) |
||||||
|
v = v << -a; |
||||||
|
else |
||||||
|
v = v >> a; |
||||||
|
|
||||||
|
return DynValue.NewNumber(v); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue lshift(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "lshift", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_a = args.AsType(1, "lshift", DataType.Number); |
||||||
|
|
||||||
|
int a = (int)v_a.Number; |
||||||
|
|
||||||
|
if (a < 0) |
||||||
|
v = v >> -a; |
||||||
|
else |
||||||
|
v = v << a; |
||||||
|
|
||||||
|
return DynValue.NewNumber(v); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue band(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewNumber(Bitwise("band", args, (x, y) => x & y)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue btest(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewBoolean(0 != Bitwise("btest", args, (x, y) => x & y)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue bor(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewNumber(Bitwise("bor", args, (x, y) => x | y)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue bnot(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "bnot", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
return DynValue.NewNumber(~v); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue bxor(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewNumber(Bitwise("bxor", args, (x, y) => x ^ y)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue lrotate(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "lrotate", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_a = args.AsType(1, "lrotate", DataType.Number); |
||||||
|
|
||||||
|
int a = ((int)v_a.Number) % 32; |
||||||
|
|
||||||
|
if (a < 0) |
||||||
|
v = (v >> (-a)) | (v << (32 + a)); |
||||||
|
else |
||||||
|
v = (v << a) | (v >> (32 - a)); |
||||||
|
|
||||||
|
return DynValue.NewNumber(v); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rrotate(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_v = args.AsType(0, "rrotate", DataType.Number); |
||||||
|
uint v = ToUInt32(v_v); |
||||||
|
|
||||||
|
DynValue v_a = args.AsType(1, "rrotate", DataType.Number); |
||||||
|
|
||||||
|
int a = ((int)v_a.Number) % 32; |
||||||
|
|
||||||
|
if (a < 0) |
||||||
|
v = (v << (-a)) | (v >> (32 + a)); |
||||||
|
else |
||||||
|
v = (v >> a) | (v << (32 - a)); |
||||||
|
|
||||||
|
return DynValue.NewNumber(v); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: c71b14e2cd41a4f70a45ea70cab3e2c7 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,127 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing coroutine Lua functions |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "coroutine")] |
||||||
|
public class CoroutineModule |
||||||
|
{ |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue create(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args[0].Type != DataType.Function && args[0].Type != DataType.ClrFunction) |
||||||
|
args.AsType(0, "create", DataType.Function); // this throws |
||||||
|
|
||||||
|
return executionContext.GetScript().CreateCoroutine(args[0]); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue wrap(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args[0].Type != DataType.Function && args[0].Type != DataType.ClrFunction) |
||||||
|
args.AsType(0, "wrap", DataType.Function); // this throws |
||||||
|
|
||||||
|
DynValue v = create(executionContext, args); |
||||||
|
DynValue c = DynValue.NewCallback(__wrap_wrapper); |
||||||
|
c.Callback.AdditionalData = v; |
||||||
|
return c; |
||||||
|
} |
||||||
|
|
||||||
|
public static DynValue __wrap_wrapper(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue handle = (DynValue)executionContext.AdditionalData; |
||||||
|
return handle.Coroutine.Resume(args.GetArray()); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue resume(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue handle = args.AsType(0, "resume", DataType.Thread); |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
DynValue ret = handle.Coroutine.Resume(args.GetArray(1)); |
||||||
|
|
||||||
|
List<DynValue> retval = new List<DynValue>(); |
||||||
|
retval.Add(DynValue.True); |
||||||
|
|
||||||
|
if (ret.Type == DataType.Tuple) |
||||||
|
{ |
||||||
|
for (int i = 0; i < ret.Tuple.Length; i++) |
||||||
|
{ |
||||||
|
var v = ret.Tuple[i]; |
||||||
|
|
||||||
|
if ((i == ret.Tuple.Length - 1) && (v.Type == DataType.Tuple)) |
||||||
|
{ |
||||||
|
retval.AddRange(v.Tuple); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
retval.Add(v); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
retval.Add(ret); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewTuple(retval.ToArray()); |
||||||
|
} |
||||||
|
catch (ScriptRuntimeException ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple( |
||||||
|
DynValue.False, |
||||||
|
DynValue.NewString(ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue yield(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewYieldReq(args.GetArray()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue running(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
Coroutine C = executionContext.GetCallingCoroutine(); |
||||||
|
return DynValue.NewTuple(DynValue.NewCoroutine(C), DynValue.NewBoolean(C.State == CoroutineState.Main)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue status(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue handle = args.AsType(0, "status", DataType.Thread); |
||||||
|
Coroutine running = executionContext.GetCallingCoroutine(); |
||||||
|
CoroutineState cs = handle.Coroutine.State; |
||||||
|
|
||||||
|
switch (cs) |
||||||
|
{ |
||||||
|
case CoroutineState.Main: |
||||||
|
case CoroutineState.Running: |
||||||
|
return (handle.Coroutine == running) ? |
||||||
|
DynValue.NewString("running") : |
||||||
|
DynValue.NewString("normal"); |
||||||
|
case CoroutineState.NotStarted: |
||||||
|
case CoroutineState.Suspended: |
||||||
|
case CoroutineState.ForceSuspended: |
||||||
|
return DynValue.NewString("suspended"); |
||||||
|
case CoroutineState.Dead: |
||||||
|
return DynValue.NewString("dead"); |
||||||
|
default: |
||||||
|
throw new InternalErrorException("Unexpected coroutine state {0}", cs); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: c160220c9253a4031baa523b549ea9e4 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,343 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter.Debugging; |
||||||
|
using MoonSharp.Interpreter.REPL; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing debug Lua functions. Support for the debug module is partial. |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "debug")] |
||||||
|
public class DebugModule |
||||||
|
{ |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue debug(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
Script script = executionContext.GetScript(); |
||||||
|
|
||||||
|
if (script.Options.DebugInput == null) |
||||||
|
throw new ScriptRuntimeException("debug.debug not supported on this platform/configuration"); |
||||||
|
|
||||||
|
ReplInterpreter interpreter = new ReplInterpreter(script) |
||||||
|
{ |
||||||
|
HandleDynamicExprs = false, |
||||||
|
HandleClassicExprsSyntax = true |
||||||
|
}; |
||||||
|
|
||||||
|
while (true) |
||||||
|
{ |
||||||
|
string s = script.Options.DebugInput(interpreter.ClassicPrompt + " "); |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
DynValue result = interpreter.Evaluate(s); |
||||||
|
|
||||||
|
if (result != null && result.Type != DataType.Void) |
||||||
|
script.Options.DebugPrint(string.Format("{0}", result)); |
||||||
|
} |
||||||
|
catch (InterpreterException ex) |
||||||
|
{ |
||||||
|
script.Options.DebugPrint(string.Format("{0}", ex.DecoratedMessage ?? ex.Message)); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
script.Options.DebugPrint(string.Format("{0}", ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue getuservalue(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v = args[0]; |
||||||
|
|
||||||
|
if (v.Type != DataType.UserData) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
return v.UserData.UserValue ?? DynValue.Nil; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue setuservalue(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v = args.AsType(0, "setuservalue", DataType.UserData, false); |
||||||
|
DynValue t = args.AsType(0, "setuservalue", DataType.Table, true); |
||||||
|
|
||||||
|
return v.UserData.UserValue = t; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue getregistry(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewTable(executionContext.GetScript().Registry); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue getmetatable(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v = args[0]; |
||||||
|
Script S = executionContext.GetScript(); |
||||||
|
|
||||||
|
if (v.Type.CanHaveTypeMetatables()) |
||||||
|
return DynValue.NewTable(S.GetTypeMetatable(v.Type)); |
||||||
|
else if (v.Type == DataType.Table) |
||||||
|
return DynValue.NewTable(v.Table.MetaTable); |
||||||
|
else |
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue setmetatable(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v = args[0]; |
||||||
|
DynValue t = args.AsType(1, "setmetatable", DataType.Table, true); |
||||||
|
Table m = (t.IsNil()) ? null : t.Table; |
||||||
|
Script S = executionContext.GetScript(); |
||||||
|
|
||||||
|
if (v.Type.CanHaveTypeMetatables()) |
||||||
|
S.SetTypeMetatable(v.Type, m); |
||||||
|
else if (v.Type == DataType.Table) |
||||||
|
v.Table.MetaTable = m; |
||||||
|
else |
||||||
|
throw new ScriptRuntimeException("cannot debug.setmetatable on type {0}", v.Type.ToErrorTypeString()); |
||||||
|
|
||||||
|
return v; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue getupvalue(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
var index = (int)args.AsType(1, "getupvalue", DataType.Number, false).Number - 1; |
||||||
|
|
||||||
|
if (args[0].Type == DataType.ClrFunction) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
var fn = args.AsType(0, "getupvalue", DataType.Function, false).Function; |
||||||
|
|
||||||
|
var closure = fn.ClosureContext; |
||||||
|
|
||||||
|
if (index < 0 || index >= closure.Count) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
return DynValue.NewTuple( |
||||||
|
DynValue.NewString(closure.Symbols[index]), |
||||||
|
closure[index]); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue upvalueid(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
var index = (int)args.AsType(1, "getupvalue", DataType.Number, false).Number - 1; |
||||||
|
|
||||||
|
if (args[0].Type == DataType.ClrFunction) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
var fn = args.AsType(0, "getupvalue", DataType.Function, false).Function; |
||||||
|
|
||||||
|
var closure = fn.ClosureContext; |
||||||
|
|
||||||
|
if (index < 0 || index >= closure.Count) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
return DynValue.NewNumber(closure[index].ReferenceID); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue setupvalue(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
var index = (int)args.AsType(1, "setupvalue", DataType.Number, false).Number - 1; |
||||||
|
|
||||||
|
if (args[0].Type == DataType.ClrFunction) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
var fn = args.AsType(0, "setupvalue", DataType.Function, false).Function; |
||||||
|
|
||||||
|
var closure = fn.ClosureContext; |
||||||
|
|
||||||
|
if (index < 0 || index >= closure.Count) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
closure[index].Assign(args[2]); |
||||||
|
|
||||||
|
return DynValue.NewString(closure.Symbols[index]); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue upvaluejoin(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue f1 = args.AsType(0, "upvaluejoin", DataType.Function, false); |
||||||
|
DynValue f2 = args.AsType(2, "upvaluejoin", DataType.Function, false); |
||||||
|
int n1 = args.AsInt(1, "upvaluejoin") - 1; |
||||||
|
int n2 = args.AsInt(3, "upvaluejoin") - 1; |
||||||
|
|
||||||
|
Closure c1 = f1.Function; |
||||||
|
Closure c2 = f2.Function; |
||||||
|
|
||||||
|
if (n1 < 0 || n1 >= c1.ClosureContext.Count) |
||||||
|
throw ScriptRuntimeException.BadArgument(1, "upvaluejoin", "invalid upvalue index"); |
||||||
|
|
||||||
|
if (n2 < 0 || n2 >= c2.ClosureContext.Count) |
||||||
|
throw ScriptRuntimeException.BadArgument(3, "upvaluejoin", "invalid upvalue index"); |
||||||
|
|
||||||
|
c2.ClosureContext[n2] = c1.ClosureContext[n1]; |
||||||
|
|
||||||
|
return DynValue.Void; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue traceback(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
|
||||||
|
DynValue vmessage = args[0]; |
||||||
|
DynValue vlevel = args[1]; |
||||||
|
|
||||||
|
double defaultSkip = 1.0; |
||||||
|
|
||||||
|
Coroutine cor = executionContext.GetCallingCoroutine(); |
||||||
|
|
||||||
|
if (vmessage.Type == DataType.Thread) |
||||||
|
{ |
||||||
|
cor = vmessage.Coroutine; |
||||||
|
vmessage = args[1]; |
||||||
|
vlevel = args[2]; |
||||||
|
defaultSkip = 0.0; |
||||||
|
} |
||||||
|
|
||||||
|
if (vmessage.IsNotNil() && vmessage.Type != DataType.String && vmessage.Type != DataType.Number) |
||||||
|
{ |
||||||
|
return vmessage; |
||||||
|
} |
||||||
|
|
||||||
|
string message = vmessage.CastToString(); |
||||||
|
|
||||||
|
int skip = (int)((vlevel.CastToNumber()) ?? defaultSkip); |
||||||
|
|
||||||
|
WatchItem[] stacktrace = cor.GetStackTrace(Math.Max(0, skip)); |
||||||
|
|
||||||
|
if (message != null) |
||||||
|
sb.AppendLine(message); |
||||||
|
|
||||||
|
sb.AppendLine("stack traceback:"); |
||||||
|
|
||||||
|
foreach (WatchItem wi in stacktrace) |
||||||
|
{ |
||||||
|
string name; |
||||||
|
|
||||||
|
if (wi.Name == null) |
||||||
|
if (wi.RetAddress < 0) |
||||||
|
name = "main chunk"; |
||||||
|
else |
||||||
|
name = "?"; |
||||||
|
else |
||||||
|
name = "function '" + wi.Name + "'"; |
||||||
|
|
||||||
|
string loc = wi.Location != null ? wi.Location.FormatLocation(executionContext.GetScript()) : "[clr]"; |
||||||
|
sb.AppendFormat("\t{0}: in {1}\n", loc, name); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewString(sb); |
||||||
|
} |
||||||
|
|
||||||
|
//[MoonSharpModuleMethod] |
||||||
|
//public static DynValue getlocal(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
//{ |
||||||
|
// Coroutine c; |
||||||
|
// int funcIdx; |
||||||
|
// Closure f; |
||||||
|
// int nextArg = ParseComplexArgs("getlocal", executionContext, args, out c, out f, out funcIdx); |
||||||
|
|
||||||
|
// int localIdx = args.AsInt(nextArg, "getlocal"); |
||||||
|
|
||||||
|
// if (f != null) |
||||||
|
// { |
||||||
|
|
||||||
|
// } |
||||||
|
// else |
||||||
|
// { |
||||||
|
|
||||||
|
// } |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//} |
||||||
|
|
||||||
|
//private static int ParseComplexArgs(string funcname, ScriptExecutionContext executionContext, CallbackArguments args, out Coroutine c, out Closure f, out int funcIdx) |
||||||
|
//{ |
||||||
|
// DynValue arg1 = args[0]; |
||||||
|
// int argbase = 0; |
||||||
|
// c = null; |
||||||
|
|
||||||
|
// if (arg1.Type == DataType.Thread) |
||||||
|
// { |
||||||
|
// c = arg1.Coroutine; |
||||||
|
// argbase = 1; |
||||||
|
// } |
||||||
|
|
||||||
|
// if (args[argbase].Type == DataType.Number) |
||||||
|
// { |
||||||
|
// funcIdx = (int)args[argbase].Number; |
||||||
|
// f = null; |
||||||
|
// } |
||||||
|
// else |
||||||
|
// { |
||||||
|
// funcIdx = -1; |
||||||
|
// f = args.AsType(argbase, funcname, DataType.Function, false).Function; |
||||||
|
// } |
||||||
|
|
||||||
|
// return argbase + 1; |
||||||
|
//} |
||||||
|
|
||||||
|
|
||||||
|
//[MoonSharpMethod] |
||||||
|
//public static DynValue getinfo(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
//{ |
||||||
|
// Coroutine cor = executionContext.GetCallingCoroutine(); |
||||||
|
// int vfArgIdx = 0; |
||||||
|
|
||||||
|
// if (args[0].Type == DataType.Thread) |
||||||
|
// cor = args[0].Coroutine; |
||||||
|
|
||||||
|
// DynValue vf = args[vfArgIdx+0]; |
||||||
|
// DynValue vwhat = args[vfArgIdx+1]; |
||||||
|
|
||||||
|
// args.AsType(vfArgIdx + 1, "getinfo", DataType.String, true); |
||||||
|
|
||||||
|
// string what = vwhat.CastToString() ?? "nfSlu"; |
||||||
|
|
||||||
|
// DynValue vt = DynValue.NewTable(executionContext.GetScript()); |
||||||
|
// Table t = vt.Table; |
||||||
|
|
||||||
|
// if (vf.Type == DataType.Function) |
||||||
|
// { |
||||||
|
// Closure f = vf.Function; |
||||||
|
// executionContext.GetInfoForFunction |
||||||
|
// } |
||||||
|
// else if (vf.Type == DataType.ClrFunction) |
||||||
|
// { |
||||||
|
|
||||||
|
// } |
||||||
|
// else if (vf.Type == DataType.Number || vf.Type == DataType.String) |
||||||
|
// { |
||||||
|
|
||||||
|
// } |
||||||
|
// else |
||||||
|
// { |
||||||
|
// args.AsType(vfArgIdx + 0, "getinfo", DataType.Number, true); |
||||||
|
// } |
||||||
|
|
||||||
|
// return vt; |
||||||
|
|
||||||
|
|
||||||
|
//} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 9b3743855cdb543c88b2320c61f28424 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,71 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing dynamic expression evaluations at runtime (a MoonSharp addition). |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "dynamic")] |
||||||
|
public class DynamicModule |
||||||
|
{ |
||||||
|
private class DynamicExprWrapper |
||||||
|
{ |
||||||
|
public DynamicExpression Expr; |
||||||
|
} |
||||||
|
|
||||||
|
public static void MoonSharpInit(Table globalTable, Table stringTable) |
||||||
|
{ |
||||||
|
UserData.RegisterType<DynamicExprWrapper>(InteropAccessMode.HideMembers); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue eval(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
if (args[0].Type == DataType.UserData) |
||||||
|
{ |
||||||
|
UserData ud = args[0].UserData; |
||||||
|
if (ud.Object is DynamicExprWrapper) |
||||||
|
{ |
||||||
|
return ((DynamicExprWrapper)ud.Object).Expr.Evaluate(executionContext); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw ScriptRuntimeException.BadArgument(0, "dynamic.eval", "A userdata was passed, but was not a previously prepared expression."); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
DynValue vs = args.AsType(0, "dynamic.eval", DataType.String, false); |
||||||
|
DynamicExpression expr = executionContext.GetScript().CreateDynamicExpression(vs.String); |
||||||
|
return expr.Evaluate(executionContext); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue prepare(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
DynValue vs = args.AsType(0, "dynamic.prepare", DataType.String, false); |
||||||
|
DynamicExpression expr = executionContext.GetScript().CreateDynamicExpression(vs.String); |
||||||
|
return UserData.Create(new DynamicExprWrapper() { Expr = expr }); |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: a82c0d3fa46554bd5857d852f9bd2812 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,132 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System.Collections.Generic; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing error handling Lua functions (pcall and xpcall) |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule] |
||||||
|
public class ErrorHandlingModule |
||||||
|
{ |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue pcall(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return SetErrorHandlerStrategy("pcall", executionContext, args, null); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static DynValue SetErrorHandlerStrategy(string funcName, |
||||||
|
ScriptExecutionContext executionContext, |
||||||
|
CallbackArguments args, |
||||||
|
DynValue handlerBeforeUnwind) |
||||||
|
{ |
||||||
|
DynValue v = args[0]; |
||||||
|
DynValue[] a = new DynValue[args.Count - 1]; |
||||||
|
|
||||||
|
for (int i = 1; i < args.Count; i++) |
||||||
|
a[i - 1] = args[i]; |
||||||
|
|
||||||
|
if (args[0].Type == DataType.ClrFunction) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
DynValue ret = args[0].Callback.Invoke(executionContext, a); |
||||||
|
if (ret.Type == DataType.TailCallRequest) |
||||||
|
{ |
||||||
|
if (ret.TailCallData.Continuation != null || ret.TailCallData.ErrorHandler != null) |
||||||
|
throw new ScriptRuntimeException("the function passed to {0} cannot be called directly by {0}. wrap in a script function instead.", funcName); |
||||||
|
|
||||||
|
return DynValue.NewTailCallReq(new TailCallData() |
||||||
|
{ |
||||||
|
Args = ret.TailCallData.Args, |
||||||
|
Function = ret.TailCallData.Function, |
||||||
|
Continuation = new CallbackFunction(pcall_continuation, funcName), |
||||||
|
ErrorHandler = new CallbackFunction(pcall_onerror, funcName), |
||||||
|
ErrorHandlerBeforeUnwind = handlerBeforeUnwind |
||||||
|
}); |
||||||
|
} |
||||||
|
else if (ret.Type == DataType.YieldRequest) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException("the function passed to {0} cannot be called directly by {0}. wrap in a script function instead.", funcName); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return DynValue.NewTupleNested(DynValue.True, ret); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (ScriptRuntimeException ex) |
||||||
|
{ |
||||||
|
executionContext.PerformMessageDecorationBeforeUnwind(handlerBeforeUnwind, ex); |
||||||
|
return DynValue.NewTupleNested(DynValue.False, DynValue.NewString(ex.DecoratedMessage)); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (args[0].Type != DataType.Function) |
||||||
|
{ |
||||||
|
return DynValue.NewTupleNested(DynValue.False, DynValue.NewString("attempt to " + funcName + " a non-function")); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return DynValue.NewTailCallReq(new TailCallData() |
||||||
|
{ |
||||||
|
Args = a, |
||||||
|
Function = v, |
||||||
|
Continuation = new CallbackFunction(pcall_continuation, funcName), |
||||||
|
ErrorHandler = new CallbackFunction(pcall_onerror, funcName), |
||||||
|
ErrorHandlerBeforeUnwind = handlerBeforeUnwind |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static DynValue MakeReturnTuple(bool retstatus, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue[] rets = new DynValue[args.Count + 1]; |
||||||
|
|
||||||
|
for (int i = 0; i < args.Count; i++) |
||||||
|
rets[i + 1] = args[i]; |
||||||
|
|
||||||
|
rets[0] = DynValue.NewBoolean(retstatus); |
||||||
|
|
||||||
|
return DynValue.NewTuple(rets); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static DynValue pcall_continuation(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return MakeReturnTuple(true, args); |
||||||
|
} |
||||||
|
|
||||||
|
public static DynValue pcall_onerror(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return MakeReturnTuple(false, args); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue xpcall(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
List<DynValue> a = new List<DynValue>(); |
||||||
|
|
||||||
|
for (int i = 0; i < args.Count; i++) |
||||||
|
{ |
||||||
|
if (i != 1) |
||||||
|
a.Add(args[i]); |
||||||
|
} |
||||||
|
|
||||||
|
DynValue handler = null; |
||||||
|
if (args[1].Type == DataType.Function || args[1].Type == DataType.ClrFunction) |
||||||
|
{ |
||||||
|
handler = args[1]; |
||||||
|
} |
||||||
|
else if (args[1].Type != DataType.Nil) |
||||||
|
{ |
||||||
|
args.AsType(1, "xpcall", DataType.Function, false); |
||||||
|
} |
||||||
|
|
||||||
|
return SetErrorHandlerStrategy("xpcall", executionContext, new CallbackArguments(a, false), handler); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 25a48a75173cc44959f158f5aed1fc00 |
||||||
|
timeCreated: 1475786653 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: d1f6f1bb70deb40239486ed094a36ea2 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,53 @@ |
|||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib.IO |
||||||
|
{ |
||||||
|
class BinaryEncoding : Encoding |
||||||
|
{ |
||||||
|
public BinaryEncoding() |
||||||
|
: base() |
||||||
|
{ |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public override int GetByteCount(char[] chars, int index, int count) |
||||||
|
{ |
||||||
|
return count; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) |
||||||
|
{ |
||||||
|
for (int i = 0; i < charCount; i++) |
||||||
|
{ |
||||||
|
bytes[byteIndex + i] = (byte)((int)chars[charIndex + i]); |
||||||
|
} |
||||||
|
|
||||||
|
return charCount; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetCharCount(byte[] bytes, int index, int count) |
||||||
|
{ |
||||||
|
return count; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) |
||||||
|
{ |
||||||
|
for (int i = 0; i < byteCount; i++) |
||||||
|
{ |
||||||
|
chars[charIndex + i] = (char)((int)bytes[byteIndex + i]); |
||||||
|
} |
||||||
|
|
||||||
|
return byteCount; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetMaxByteCount(int charCount) |
||||||
|
{ |
||||||
|
return charCount; |
||||||
|
} |
||||||
|
|
||||||
|
public override int GetMaxCharCount(int byteCount) |
||||||
|
{ |
||||||
|
return byteCount; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 675a461a252db43b0a24db05a6dbeabc |
||||||
|
timeCreated: 1475786654 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,21 @@ |
|||||||
|
using System.IO; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib.IO |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Abstract class implementing a file Lua userdata. Methods are meant to be called by Lua code. |
||||||
|
/// </summary> |
||||||
|
internal class FileUserData : StreamFileUserDataBase |
||||||
|
{ |
||||||
|
public FileUserData(Script script, string filename, Encoding encoding, string mode) |
||||||
|
{ |
||||||
|
Stream stream = Script.GlobalOptions.Platform.IO_OpenFile(script, filename, encoding, mode); |
||||||
|
|
||||||
|
StreamReader reader = (stream.CanRead) ? new StreamReader(stream, encoding) : null; |
||||||
|
StreamWriter writer = (stream.CanWrite) ? new StreamWriter(stream, encoding) : null; |
||||||
|
|
||||||
|
base.Initialize(stream, reader, writer); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: af797d1c8ef1a415ca0a84f11c04a6f5 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,225 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using MoonSharp.Interpreter.Compatibility; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib.IO |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Abstract class implementing a file Lua userdata. Methods are meant to be called by Lua code. |
||||||
|
/// </summary> |
||||||
|
internal abstract class FileUserDataBase : RefIdObject |
||||||
|
{ |
||||||
|
public DynValue lines(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
List<DynValue> readLines = new List<DynValue>(); |
||||||
|
|
||||||
|
DynValue readValue = null; |
||||||
|
|
||||||
|
do |
||||||
|
{ |
||||||
|
readValue = read(executionContext, args); |
||||||
|
readLines.Add(readValue); |
||||||
|
|
||||||
|
} while (readValue.IsNotNil()); |
||||||
|
|
||||||
|
return DynValue.FromObject(executionContext.GetScript(), readLines.Select(s => s)); |
||||||
|
} |
||||||
|
|
||||||
|
public DynValue read(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args.Count == 0) |
||||||
|
{ |
||||||
|
string str = ReadLine(); |
||||||
|
|
||||||
|
if (str == null) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
str = str.TrimEnd('\n', '\r'); |
||||||
|
return DynValue.NewString(str); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
List<DynValue> rets = new List<DynValue>(); |
||||||
|
|
||||||
|
for (int i = 0; i < args.Count; i++) |
||||||
|
{ |
||||||
|
DynValue v; |
||||||
|
|
||||||
|
if (args[i].Type == DataType.Number) |
||||||
|
{ |
||||||
|
if (Eof()) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
int howmany = (int)args[i].Number; |
||||||
|
|
||||||
|
string str = ReadBuffer(howmany); |
||||||
|
v = DynValue.NewString(str); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
string opt = args.AsType(i, "read", DataType.String, false).String; |
||||||
|
|
||||||
|
if (Eof()) |
||||||
|
{ |
||||||
|
v = opt.StartsWith("*a") ? DynValue.NewString("") : DynValue.Nil; |
||||||
|
} |
||||||
|
else if (opt.StartsWith("*n")) |
||||||
|
{ |
||||||
|
double? d = ReadNumber(); |
||||||
|
|
||||||
|
if (d.HasValue) |
||||||
|
v = DynValue.NewNumber(d.Value); |
||||||
|
else |
||||||
|
v = DynValue.Nil; |
||||||
|
} |
||||||
|
else if (opt.StartsWith("*a")) |
||||||
|
{ |
||||||
|
string str = ReadToEnd(); |
||||||
|
v = DynValue.NewString(str); |
||||||
|
} |
||||||
|
else if (opt.StartsWith("*l")) |
||||||
|
{ |
||||||
|
string str = ReadLine(); |
||||||
|
str = str.TrimEnd('\n', '\r'); |
||||||
|
v = DynValue.NewString(str); |
||||||
|
} |
||||||
|
else if (opt.StartsWith("*L")) |
||||||
|
{ |
||||||
|
string str = ReadLine(); |
||||||
|
|
||||||
|
str = str.TrimEnd('\n', '\r'); |
||||||
|
str += "\n"; |
||||||
|
|
||||||
|
v = DynValue.NewString(str); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw ScriptRuntimeException.BadArgument(i, "read", "invalid option"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
rets.Add(v); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewTuple(rets.ToArray()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public DynValue write(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
for (int i = 0; i < args.Count; i++) |
||||||
|
{ |
||||||
|
//string str = args.AsStringUsingMeta(executionContext, i, "file:write"); |
||||||
|
string str = args.AsType(i, "write", DataType.String, false).String; |
||||||
|
Write(str); |
||||||
|
} |
||||||
|
|
||||||
|
return UserData.Create(this); |
||||||
|
} |
||||||
|
catch (ScriptRuntimeException) |
||||||
|
{ |
||||||
|
throw; |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public DynValue close(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
string msg = Close(); |
||||||
|
if (msg == null) |
||||||
|
return DynValue.True; |
||||||
|
else |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(msg)); |
||||||
|
} |
||||||
|
catch (ScriptRuntimeException) |
||||||
|
{ |
||||||
|
throw; |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
double? ReadNumber() |
||||||
|
{ |
||||||
|
string chr = ""; |
||||||
|
|
||||||
|
while (!Eof()) |
||||||
|
{ |
||||||
|
char c = Peek(); |
||||||
|
if (char.IsWhiteSpace(c)) |
||||||
|
{ |
||||||
|
ReadBuffer(1); |
||||||
|
} |
||||||
|
else if (IsNumericChar(c, chr)) |
||||||
|
{ |
||||||
|
ReadBuffer(1); |
||||||
|
chr += c; |
||||||
|
} |
||||||
|
else break; |
||||||
|
} |
||||||
|
|
||||||
|
double d; |
||||||
|
|
||||||
|
if (double.TryParse(chr, out d)) |
||||||
|
{ |
||||||
|
return d; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private bool IsNumericChar(char c, string numAsFar) |
||||||
|
{ |
||||||
|
if (char.IsDigit(c)) |
||||||
|
return true; |
||||||
|
|
||||||
|
if (c == '-') |
||||||
|
return numAsFar.Length == 0; |
||||||
|
|
||||||
|
if (c == '.') |
||||||
|
return !Framework.Do.StringContainsChar(numAsFar, '.'); |
||||||
|
|
||||||
|
if (c == 'E' || c == 'e') |
||||||
|
return !(Framework.Do.StringContainsChar(numAsFar, 'E') || Framework.Do.StringContainsChar(numAsFar, 'e')); |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract bool Eof(); |
||||||
|
protected abstract string ReadLine(); |
||||||
|
protected abstract string ReadBuffer(int p); |
||||||
|
protected abstract string ReadToEnd(); |
||||||
|
protected abstract char Peek(); |
||||||
|
protected abstract void Write(string value); |
||||||
|
|
||||||
|
|
||||||
|
protected internal abstract bool isopen(); |
||||||
|
protected abstract string Close(); |
||||||
|
|
||||||
|
public abstract bool flush(); |
||||||
|
public abstract long seek(string whence, long offset); |
||||||
|
public abstract bool setvbuf(string mode); |
||||||
|
|
||||||
|
public override string ToString() |
||||||
|
{ |
||||||
|
if (isopen()) |
||||||
|
return string.Format("file ({0:X8})", base.ReferenceID); |
||||||
|
else |
||||||
|
return "file (closed)"; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1e0c682730fd243eca755897f724ff91 |
||||||
|
timeCreated: 1476432878 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,31 @@ |
|||||||
|
using System.IO; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib.IO |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Abstract class implementing an unclosable file Lua userdata. Methods are meant to be called by Lua code. |
||||||
|
/// </summary> |
||||||
|
internal class StandardIOFileUserDataBase : StreamFileUserDataBase |
||||||
|
{ |
||||||
|
protected override string Close() |
||||||
|
{ |
||||||
|
return ("cannot close standard file"); |
||||||
|
} |
||||||
|
|
||||||
|
public static StandardIOFileUserDataBase CreateInputStream(Stream stream) |
||||||
|
{ |
||||||
|
var f = new StandardIOFileUserDataBase(); |
||||||
|
f.Initialize(stream, new StreamReader(stream), null); |
||||||
|
return f; |
||||||
|
} |
||||||
|
|
||||||
|
public static StandardIOFileUserDataBase CreateOutputStream(Stream stream) |
||||||
|
{ |
||||||
|
var f = new StandardIOFileUserDataBase(); |
||||||
|
f.Initialize(stream, null, new StreamWriter(stream)); |
||||||
|
return f; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: c1fccf4c28e9a4667a0a6984cb2c736d |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,140 @@ |
|||||||
|
using System.IO; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib.IO |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Abstract class implementing a file Lua userdata. Methods are meant to be called by Lua code. |
||||||
|
/// </summary> |
||||||
|
internal abstract class StreamFileUserDataBase : FileUserDataBase |
||||||
|
{ |
||||||
|
protected Stream m_Stream; |
||||||
|
protected StreamReader m_Reader; |
||||||
|
protected StreamWriter m_Writer; |
||||||
|
protected bool m_Closed = false; |
||||||
|
|
||||||
|
|
||||||
|
protected void Initialize(Stream stream, StreamReader reader, StreamWriter writer) |
||||||
|
{ |
||||||
|
m_Stream = stream; |
||||||
|
m_Reader = reader; |
||||||
|
m_Writer = writer; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private void CheckFileIsNotClosed() |
||||||
|
{ |
||||||
|
if (m_Closed) |
||||||
|
throw new ScriptRuntimeException("attempt to use a closed file"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
protected override bool Eof() |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
|
||||||
|
if (m_Reader != null) |
||||||
|
return m_Reader.EndOfStream; |
||||||
|
else |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
protected override string ReadLine() |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
return m_Reader.ReadLine(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override string ReadToEnd() |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
return m_Reader.ReadToEnd(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override string ReadBuffer(int p) |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
char[] buffer = new char[p]; |
||||||
|
int length = m_Reader.ReadBlock(buffer, 0, p); |
||||||
|
return new string(buffer, 0, length); |
||||||
|
} |
||||||
|
|
||||||
|
protected override char Peek() |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
return (char)m_Reader.Peek(); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void Write(string value) |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
m_Writer.Write(value); |
||||||
|
} |
||||||
|
|
||||||
|
protected override string Close() |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
|
||||||
|
if (m_Writer != null) |
||||||
|
m_Writer.Dispose(); |
||||||
|
|
||||||
|
if (m_Reader != null) |
||||||
|
m_Reader.Dispose(); |
||||||
|
|
||||||
|
m_Stream.Dispose(); |
||||||
|
|
||||||
|
m_Closed = true; |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool flush() |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
|
||||||
|
if (m_Writer != null) |
||||||
|
m_Writer.Flush(); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public override long seek(string whence, long offset) |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
if (whence != null) |
||||||
|
{ |
||||||
|
if (whence == "set") |
||||||
|
{ |
||||||
|
m_Stream.Seek(offset, SeekOrigin.Begin); |
||||||
|
} |
||||||
|
else if (whence == "cur") |
||||||
|
{ |
||||||
|
m_Stream.Seek(offset, SeekOrigin.Current); |
||||||
|
} |
||||||
|
else if (whence == "end") |
||||||
|
{ |
||||||
|
m_Stream.Seek(offset, SeekOrigin.End); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw ScriptRuntimeException.BadArgument(0, "seek", "invalid option '" + whence + "'"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return m_Stream.Position; |
||||||
|
} |
||||||
|
|
||||||
|
public override bool setvbuf(string mode) |
||||||
|
{ |
||||||
|
CheckFileIsNotClosed(); |
||||||
|
if (m_Writer != null) |
||||||
|
m_Writer.AutoFlush = (mode == "no" || mode == "line"); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
protected internal override bool isopen() |
||||||
|
{ |
||||||
|
return !m_Closed; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 07ffca2aa60ad4febb46043b8eb2b531 |
||||||
|
timeCreated: 1475786653 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,309 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter.Compatibility; |
||||||
|
using MoonSharp.Interpreter.CoreLib.IO; |
||||||
|
using MoonSharp.Interpreter.Platforms; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing io Lua functions. Proper support requires a compatible IPlatformAccessor |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "io")] |
||||||
|
public class IoModule |
||||||
|
{ |
||||||
|
public static void MoonSharpInit(Table globalTable, Table ioTable) |
||||||
|
{ |
||||||
|
UserData.RegisterType<FileUserDataBase>(InteropAccessMode.Default, "file"); |
||||||
|
|
||||||
|
Table meta = new Table(ioTable.OwnerScript); |
||||||
|
DynValue __index = DynValue.NewCallback(new CallbackFunction(__index_callback, "__index_callback")); |
||||||
|
meta.Set("__index", __index); |
||||||
|
ioTable.MetaTable = meta; |
||||||
|
|
||||||
|
SetStandardFile(globalTable.OwnerScript, StandardFileType.StdIn, globalTable.OwnerScript.Options.Stdin); |
||||||
|
SetStandardFile(globalTable.OwnerScript, StandardFileType.StdOut, globalTable.OwnerScript.Options.Stdout); |
||||||
|
SetStandardFile(globalTable.OwnerScript, StandardFileType.StdErr, globalTable.OwnerScript.Options.Stderr); |
||||||
|
} |
||||||
|
|
||||||
|
private static DynValue __index_callback(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
string name = args[1].CastToString(); |
||||||
|
|
||||||
|
if (name == "stdin") |
||||||
|
return GetStandardFile(executionContext.GetScript(), StandardFileType.StdIn); |
||||||
|
else if (name == "stdout") |
||||||
|
return GetStandardFile(executionContext.GetScript(), StandardFileType.StdOut); |
||||||
|
else if (name == "stderr") |
||||||
|
return GetStandardFile(executionContext.GetScript(), StandardFileType.StdErr); |
||||||
|
else |
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
|
||||||
|
private static DynValue GetStandardFile(Script S, StandardFileType file) |
||||||
|
{ |
||||||
|
Table R = S.Registry; |
||||||
|
|
||||||
|
DynValue ff = R.Get("853BEAAF298648839E2C99D005E1DF94_STD_" + file.ToString()); |
||||||
|
return ff; |
||||||
|
} |
||||||
|
|
||||||
|
private static void SetStandardFile(Script S, StandardFileType file, Stream optionsStream) |
||||||
|
{ |
||||||
|
Table R = S.Registry; |
||||||
|
|
||||||
|
optionsStream = optionsStream ?? Script.GlobalOptions.Platform.IO_GetStandardStream(file); |
||||||
|
|
||||||
|
FileUserDataBase udb = null; |
||||||
|
|
||||||
|
if (file == StandardFileType.StdIn) |
||||||
|
udb = StandardIOFileUserDataBase.CreateInputStream(optionsStream); |
||||||
|
else |
||||||
|
udb = StandardIOFileUserDataBase.CreateOutputStream(optionsStream); |
||||||
|
|
||||||
|
R.Set("853BEAAF298648839E2C99D005E1DF94_STD_" + file.ToString(), UserData.Create(udb)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static FileUserDataBase GetDefaultFile(ScriptExecutionContext executionContext, StandardFileType file) |
||||||
|
{ |
||||||
|
Table R = executionContext.GetScript().Registry; |
||||||
|
|
||||||
|
DynValue ff = R.Get("853BEAAF298648839E2C99D005E1DF94_" + file.ToString()); |
||||||
|
|
||||||
|
if (ff.IsNil()) |
||||||
|
{ |
||||||
|
ff = GetStandardFile(executionContext.GetScript(), file); |
||||||
|
} |
||||||
|
|
||||||
|
return ff.CheckUserDataType<FileUserDataBase>("getdefaultfile(" + file.ToString() + ")"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
static void SetDefaultFile(ScriptExecutionContext executionContext, StandardFileType file, FileUserDataBase fileHandle) |
||||||
|
{ |
||||||
|
SetDefaultFile(executionContext.GetScript(), file, fileHandle); |
||||||
|
} |
||||||
|
|
||||||
|
internal static void SetDefaultFile(Script script, StandardFileType file, FileUserDataBase fileHandle) |
||||||
|
{ |
||||||
|
Table R = script.Registry; |
||||||
|
R.Set("853BEAAF298648839E2C99D005E1DF94_" + file.ToString(), UserData.Create(fileHandle)); |
||||||
|
} |
||||||
|
|
||||||
|
public static void SetDefaultFile(Script script, StandardFileType file, Stream stream) |
||||||
|
{ |
||||||
|
if (file == StandardFileType.StdIn) |
||||||
|
SetDefaultFile(script, file, StandardIOFileUserDataBase.CreateInputStream(stream)); |
||||||
|
else |
||||||
|
SetDefaultFile(script, file, StandardIOFileUserDataBase.CreateOutputStream(stream)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue close(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
FileUserDataBase outp = args.AsUserData<FileUserDataBase>(0, "close", true) ?? GetDefaultFile(executionContext, StandardFileType.StdOut); |
||||||
|
return outp.close(executionContext, args); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue flush(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
FileUserDataBase outp = args.AsUserData<FileUserDataBase>(0, "close", true) ?? GetDefaultFile(executionContext, StandardFileType.StdOut); |
||||||
|
outp.flush(); |
||||||
|
return DynValue.True; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue input(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return HandleDefaultStreamSetter(executionContext, args, StandardFileType.StdIn); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue output(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return HandleDefaultStreamSetter(executionContext, args, StandardFileType.StdOut); |
||||||
|
} |
||||||
|
|
||||||
|
private static DynValue HandleDefaultStreamSetter(ScriptExecutionContext executionContext, CallbackArguments args, StandardFileType defaultFiles) |
||||||
|
{ |
||||||
|
if (args.Count == 0 || args[0].IsNil()) |
||||||
|
{ |
||||||
|
var file = GetDefaultFile(executionContext, defaultFiles); |
||||||
|
return UserData.Create(file); |
||||||
|
} |
||||||
|
|
||||||
|
FileUserDataBase inp = null; |
||||||
|
|
||||||
|
if (args[0].Type == DataType.String || args[0].Type == DataType.Number) |
||||||
|
{ |
||||||
|
string fileName = args[0].CastToString(); |
||||||
|
inp = Open(executionContext, fileName, GetUTF8Encoding(), defaultFiles == StandardFileType.StdIn ? "r" : "w"); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
inp = args.AsUserData<FileUserDataBase>(0, defaultFiles == StandardFileType.StdIn ? "input" : "output", false); |
||||||
|
} |
||||||
|
|
||||||
|
SetDefaultFile(executionContext, defaultFiles, inp); |
||||||
|
|
||||||
|
return UserData.Create(inp); |
||||||
|
} |
||||||
|
|
||||||
|
private static Encoding GetUTF8Encoding() |
||||||
|
{ |
||||||
|
return new System.Text.UTF8Encoding(false); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue lines(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
string filename = args.AsType(0, "lines", DataType.String, false).String; |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
List<DynValue> readLines = new List<DynValue>(); |
||||||
|
|
||||||
|
using (var stream = Script.GlobalOptions.Platform.IO_OpenFile(executionContext.GetScript(), filename, null, "r")) |
||||||
|
{ |
||||||
|
using (var reader = new System.IO.StreamReader(stream)) |
||||||
|
{ |
||||||
|
while (!reader.EndOfStream) |
||||||
|
{ |
||||||
|
string line = reader.ReadLine(); |
||||||
|
readLines.Add(DynValue.NewString(line)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
readLines.Add(DynValue.Nil); |
||||||
|
|
||||||
|
return DynValue.FromObject(executionContext.GetScript(), readLines.Select(s => s)); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException(IoExceptionToLuaMessage(ex, filename)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue open(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
string filename = args.AsType(0, "open", DataType.String, false).String; |
||||||
|
DynValue vmode = args.AsType(1, "open", DataType.String, true); |
||||||
|
DynValue vencoding = args.AsType(2, "open", DataType.String, true); |
||||||
|
|
||||||
|
string mode = vmode.IsNil() ? "r" : vmode.String; |
||||||
|
|
||||||
|
string invalidChars = mode.Replace("+", "") |
||||||
|
.Replace("r", "") |
||||||
|
.Replace("a", "") |
||||||
|
.Replace("w", "") |
||||||
|
.Replace("b", "") |
||||||
|
.Replace("t", ""); |
||||||
|
|
||||||
|
if (invalidChars.Length > 0) |
||||||
|
throw ScriptRuntimeException.BadArgument(1, "open", "invalid mode"); |
||||||
|
|
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
string encoding = vencoding.IsNil() ? null : vencoding.String; |
||||||
|
|
||||||
|
// list of codes: http://msdn.microsoft.com/en-us/library/vstudio/system.text.encoding%28v=vs.90%29.aspx. |
||||||
|
// In addition, "binary" is available. |
||||||
|
Encoding e = null; |
||||||
|
bool isBinary = Framework.Do.StringContainsChar(mode, 'b'); |
||||||
|
|
||||||
|
if (encoding == "binary") |
||||||
|
{ |
||||||
|
isBinary = true; |
||||||
|
e = new BinaryEncoding(); |
||||||
|
} |
||||||
|
else if (encoding == null) |
||||||
|
{ |
||||||
|
if (!isBinary) e = GetUTF8Encoding(); |
||||||
|
else e = new BinaryEncoding(); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
if (isBinary) |
||||||
|
throw new ScriptRuntimeException("Can't specify encodings other than nil or 'binary' for binary streams."); |
||||||
|
|
||||||
|
e = Encoding.GetEncoding(encoding); |
||||||
|
} |
||||||
|
|
||||||
|
return UserData.Create(Open(executionContext, filename, e, mode)); |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, |
||||||
|
DynValue.NewString(IoExceptionToLuaMessage(ex, filename))); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
public static string IoExceptionToLuaMessage(Exception ex, string filename) |
||||||
|
{ |
||||||
|
if (ex is System.IO.FileNotFoundException) |
||||||
|
return string.Format("{0}: No such file or directory", filename); |
||||||
|
else |
||||||
|
return ex.Message; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue type(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args[0].Type != DataType.UserData) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
FileUserDataBase file = args[0].UserData.Object as FileUserDataBase; |
||||||
|
|
||||||
|
if (file == null) |
||||||
|
return DynValue.Nil; |
||||||
|
else if (file.isopen()) |
||||||
|
return DynValue.NewString("file"); |
||||||
|
else |
||||||
|
return DynValue.NewString("closed file"); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue read(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
FileUserDataBase file = GetDefaultFile(executionContext, StandardFileType.StdIn); |
||||||
|
return file.read(executionContext, args); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue write(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
FileUserDataBase file = GetDefaultFile(executionContext, StandardFileType.StdOut); |
||||||
|
return file.write(executionContext, args); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue tmpfile(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
string tmpfilename = Script.GlobalOptions.Platform.IO_OS_GetTempFilename(); |
||||||
|
FileUserDataBase file = Open(executionContext, tmpfilename, GetUTF8Encoding(), "w"); |
||||||
|
return UserData.Create(file); |
||||||
|
} |
||||||
|
|
||||||
|
private static FileUserDataBase Open(ScriptExecutionContext executionContext, string filename, Encoding encoding, string mode) |
||||||
|
{ |
||||||
|
return new FileUserData(executionContext.GetScript(), filename, encoding, mode); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 5209e5cca6a8f4dbc888ed4b7e061d55 |
||||||
|
timeCreated: 1476432882 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,55 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using MoonSharp.Interpreter.Serialization.Json; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
[MoonSharpModule(Namespace = "json")] |
||||||
|
public class JsonModule |
||||||
|
{ |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue parse(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
DynValue vs = args.AsType(0, "parse", DataType.String, false); |
||||||
|
Table t = JsonTableConverter.JsonToTable(vs.String, executionContext.GetScript()); |
||||||
|
return DynValue.NewTable(t); |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue serialize(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
DynValue vt = args.AsType(0, "serialize", DataType.Table, false); |
||||||
|
string s = JsonTableConverter.TableToJson(vt.Table); |
||||||
|
return DynValue.NewString(s); |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue isnull(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue vs = args[0]; |
||||||
|
return DynValue.NewBoolean((JsonNull.IsJsonNull(vs)) || (vs.IsNil())); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue @null(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return JsonNull.Create(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: df9d3ec3d79f5431c88af4ab97b6f18a |
||||||
|
timeCreated: 1475786656 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,248 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing loading Lua functions like 'require', 'load', etc. |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule] |
||||||
|
public class LoadModule |
||||||
|
{ |
||||||
|
public static void MoonSharpInit(Table globalTable, Table ioTable) |
||||||
|
{ |
||||||
|
DynValue package = globalTable.Get("package"); |
||||||
|
|
||||||
|
if (package.IsNil()) |
||||||
|
{ |
||||||
|
package = DynValue.NewTable(globalTable.OwnerScript); |
||||||
|
globalTable["package"] = package; |
||||||
|
} |
||||||
|
else if (package.Type != DataType.Table) |
||||||
|
{ |
||||||
|
throw new InternalErrorException("'package' global variable was found and it is not a table"); |
||||||
|
} |
||||||
|
|
||||||
|
#if PCL || ENABLE_DOTNET || NETFX_CORE |
||||||
|
string cfg = "\\\n;\n?\n!\n-\n"; |
||||||
|
#else |
||||||
|
string cfg = System.IO.Path.DirectorySeparatorChar + "\n;\n?\n!\n-\n"; |
||||||
|
#endif |
||||||
|
|
||||||
|
package.Table.Set("config", DynValue.NewString(cfg)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// load (ld [, source [, mode [, env]]]) |
||||||
|
// ---------------------------------------------------------------- |
||||||
|
// Loads a chunk. |
||||||
|
// |
||||||
|
// If ld is a string, the chunk is this string. |
||||||
|
// |
||||||
|
// If there are no syntactic errors, returns the compiled chunk as a function; |
||||||
|
// otherwise, returns nil plus the error message. |
||||||
|
// |
||||||
|
// source is used as the source of the chunk for error messages and debug |
||||||
|
// information (see §4.9). When absent, it defaults to ld, if ld is a string, |
||||||
|
// or to "=(load)" otherwise. |
||||||
|
// |
||||||
|
// The string mode is ignored, and assumed to be "t"; |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue load(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return load_impl(executionContext, args, null); |
||||||
|
} |
||||||
|
|
||||||
|
// loadsafe (ld [, source [, mode [, env]]]) |
||||||
|
// ---------------------------------------------------------------- |
||||||
|
// Same as load, except that "env" defaults to the current environment of the function |
||||||
|
// calling load, instead of the actual global environment. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue loadsafe(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return load_impl(executionContext, args, GetSafeDefaultEnv(executionContext)); |
||||||
|
} |
||||||
|
|
||||||
|
public static DynValue load_impl(ScriptExecutionContext executionContext, CallbackArguments args, Table defaultEnv) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
Script S = executionContext.GetScript(); |
||||||
|
DynValue ld = args[0]; |
||||||
|
string script = ""; |
||||||
|
|
||||||
|
if (ld.Type == DataType.Function) |
||||||
|
{ |
||||||
|
while (true) |
||||||
|
{ |
||||||
|
DynValue ret = executionContext.GetScript().Call(ld); |
||||||
|
if (ret.Type == DataType.String && ret.String.Length > 0) |
||||||
|
script += ret.String; |
||||||
|
else if (ret.IsNil()) |
||||||
|
break; |
||||||
|
else |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString("reader function must return a string")); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (ld.Type == DataType.String) |
||||||
|
{ |
||||||
|
script = ld.String; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
args.AsType(0, "load", DataType.Function, false); |
||||||
|
} |
||||||
|
|
||||||
|
DynValue source = args.AsType(1, "load", DataType.String, true); |
||||||
|
DynValue env = args.AsType(3, "load", DataType.Table, true); |
||||||
|
|
||||||
|
DynValue fn = S.LoadString(script, |
||||||
|
!env.IsNil() ? env.Table : defaultEnv, |
||||||
|
!source.IsNil() ? source.String : "=(load)"); |
||||||
|
|
||||||
|
return fn; |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.DecoratedMessage ?? ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// loadfile ([filename [, mode [, env]]]) |
||||||
|
// ---------------------------------------------------------------- |
||||||
|
// Similar to load, but gets the chunk from file filename or from the standard input, |
||||||
|
// if no file name is given. INCOMPAT: stdin not supported, mode ignored |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue loadfile(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return loadfile_impl(executionContext, args, null); |
||||||
|
} |
||||||
|
|
||||||
|
// loadfile ([filename [, mode [, env]]]) |
||||||
|
// ---------------------------------------------------------------- |
||||||
|
// Same as loadfile, except that "env" defaults to the current environment of the function |
||||||
|
// calling load, instead of the actual global environment. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue loadfilesafe(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return loadfile_impl(executionContext, args, GetSafeDefaultEnv(executionContext)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static DynValue loadfile_impl(ScriptExecutionContext executionContext, CallbackArguments args, Table defaultEnv) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
Script S = executionContext.GetScript(); |
||||||
|
DynValue filename = args.AsType(0, "loadfile", DataType.String, false); |
||||||
|
DynValue env = args.AsType(2, "loadfile", DataType.Table, true); |
||||||
|
|
||||||
|
DynValue fn = S.LoadFile(filename.String, env.IsNil() ? defaultEnv : env.Table); |
||||||
|
|
||||||
|
return fn; |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.DecoratedMessage ?? ex.Message)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static Table GetSafeDefaultEnv(ScriptExecutionContext executionContext) |
||||||
|
{ |
||||||
|
Table env = executionContext.CurrentGlobalEnv; |
||||||
|
|
||||||
|
if (env == null) |
||||||
|
throw new ScriptRuntimeException("current environment cannot be backtracked."); |
||||||
|
|
||||||
|
return env; |
||||||
|
} |
||||||
|
|
||||||
|
//dofile ([filename]) |
||||||
|
//-------------------------------------------------------------------------------------------------------------- |
||||||
|
//Opens the named file and executes its contents as a Lua chunk. When called without arguments, |
||||||
|
//dofile executes the contents of the standard input (stdin). Returns all values returned by the chunk. |
||||||
|
//In case of errors, dofile propagates the error to its caller (that is, dofile does not run in protected mode). |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue dofile(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
Script S = executionContext.GetScript(); |
||||||
|
DynValue v = args.AsType(0, "dofile", DataType.String, false); |
||||||
|
|
||||||
|
DynValue fn = S.LoadFile(v.String); |
||||||
|
|
||||||
|
return DynValue.NewTailCallReq(fn); // tail call to dofile |
||||||
|
} |
||||||
|
catch (SyntaxErrorException ex) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//require (modname) |
||||||
|
//---------------------------------------------------------------------------------------------------------------- |
||||||
|
//Loads the given module. The function starts by looking into the package.loaded table to determine whether |
||||||
|
//modname is already loaded. If it is, then require returns the value stored at package.loaded[modname]. |
||||||
|
//Otherwise, it tries to find a loader for the module. |
||||||
|
// |
||||||
|
//To find a loader, require is guided by the package.loaders array. By changing this array, we can change |
||||||
|
//how require looks for a module. The following explanation is based on the default configuration for package.loaders. |
||||||
|
// |
||||||
|
//First require queries package.preload[modname]. If it has a value, this value (which should be a function) |
||||||
|
//is the loader. Otherwise require searches for a Lua loader using the path stored in package.path. |
||||||
|
//If that also fails, it searches for a C loader using the path stored in package.cpath. If that also fails, |
||||||
|
//it tries an all-in-one loader (see package.loaders). |
||||||
|
// |
||||||
|
//Once a loader is found, require calls the loader with a single argument, modname. If the loader returns any value, |
||||||
|
//require assigns the returned value to package.loaded[modname]. If the loader returns no value and has not assigned |
||||||
|
//any value to package.loaded[modname], then require assigns true to this entry. In any case, require returns the |
||||||
|
//final value of package.loaded[modname]. |
||||||
|
// |
||||||
|
//If there is any error loading or running the module, or if it cannot find any loader for the module, then require |
||||||
|
//signals an error. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue __require_clr_impl(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
Script S = executionContext.GetScript(); |
||||||
|
DynValue v = args.AsType(0, "__require_clr_impl", DataType.String, false); |
||||||
|
|
||||||
|
DynValue fn = S.RequireModule(v.String); |
||||||
|
|
||||||
|
return fn; // tail call to dofile |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public const string require = @"
|
||||||
|
function(modulename) |
||||||
|
if (package == nil) then package = { }; end |
||||||
|
if (package.loaded == nil) then package.loaded = { }; end |
||||||
|
|
||||||
|
local m = package.loaded[modulename]; |
||||||
|
|
||||||
|
if (m ~= nil) then |
||||||
|
return m; |
||||||
|
end |
||||||
|
|
||||||
|
local func = __require_clr_impl(modulename); |
||||||
|
|
||||||
|
local res = func(modulename); |
||||||
|
|
||||||
|
if (res == nil) then |
||||||
|
res = true; |
||||||
|
end |
||||||
|
|
||||||
|
package.loaded[modulename] = res; |
||||||
|
|
||||||
|
return res; |
||||||
|
end";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 90b319234a9a342b6a8649eef72352fd |
||||||
|
timeCreated: 1476432884 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,324 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
using MoonSharp.Interpreter.Interop; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing math Lua functions |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "math")] |
||||||
|
public class MathModule |
||||||
|
{ |
||||||
|
[MoonSharpModuleConstant] |
||||||
|
public const double pi = Math.PI; |
||||||
|
[MoonSharpModuleConstant] |
||||||
|
public const double huge = double.MaxValue; |
||||||
|
|
||||||
|
private static Random GetRandom(Script s) |
||||||
|
{ |
||||||
|
DynValue rr = s.Registry.Get("F61E3AA7247D4D1EB7A45430B0C8C9BB_MATH_RANDOM"); |
||||||
|
return (rr.UserData.Object as AnonWrapper<Random>).Value; |
||||||
|
} |
||||||
|
|
||||||
|
private static void SetRandom(Script s, Random random) |
||||||
|
{ |
||||||
|
DynValue rr = UserData.Create(new AnonWrapper<Random>(random)); |
||||||
|
s.Registry.Set("F61E3AA7247D4D1EB7A45430B0C8C9BB_MATH_RANDOM", rr); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public static void MoonSharpInit(Table globalTable, Table ioTable) |
||||||
|
{ |
||||||
|
SetRandom(globalTable.OwnerScript, new Random()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static DynValue exec1(CallbackArguments args, string funcName, Func<double, double> func) |
||||||
|
{ |
||||||
|
DynValue arg = args.AsType(0, funcName, DataType.Number, false); |
||||||
|
return DynValue.NewNumber(func(arg.Number)); |
||||||
|
} |
||||||
|
|
||||||
|
private static DynValue exec2(CallbackArguments args, string funcName, Func<double, double, double> func) |
||||||
|
{ |
||||||
|
DynValue arg = args.AsType(0, funcName, DataType.Number, false); |
||||||
|
DynValue arg2 = args.AsType(1, funcName, DataType.Number, false); |
||||||
|
return DynValue.NewNumber(func(arg.Number, arg2.Number)); |
||||||
|
} |
||||||
|
private static DynValue exec2n(CallbackArguments args, string funcName, double defVal, Func<double, double, double> func) |
||||||
|
{ |
||||||
|
DynValue arg = args.AsType(0, funcName, DataType.Number, false); |
||||||
|
DynValue arg2 = args.AsType(1, funcName, DataType.Number, true); |
||||||
|
|
||||||
|
return DynValue.NewNumber(func(arg.Number, arg2.IsNil() ? defVal : arg2.Number)); |
||||||
|
} |
||||||
|
private static DynValue execaccum(CallbackArguments args, string funcName, Func<double, double, double> func) |
||||||
|
{ |
||||||
|
double accum = double.NaN; |
||||||
|
|
||||||
|
if (args.Count == 0) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException("bad argument #1 to '{0}' (number expected, got no value)", funcName); |
||||||
|
} |
||||||
|
|
||||||
|
for (int i = 0; i < args.Count; i++) |
||||||
|
{ |
||||||
|
DynValue arg = args.AsType(i, funcName, DataType.Number, false); |
||||||
|
|
||||||
|
if (i == 0) |
||||||
|
accum = arg.Number; |
||||||
|
else |
||||||
|
accum = func(accum, arg.Number); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewNumber(accum); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue abs(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "abs", d => Math.Abs(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue acos(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "acos", d => Math.Acos(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue asin(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "asin", d => Math.Asin(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue atan(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "atan", d => Math.Atan(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue atan2(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec2(args, "atan2", (d1, d2) => Math.Atan2(d1, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue ceil(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "ceil", d => Math.Ceiling(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue cos(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "cos", d => Math.Cos(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue cosh(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "cosh", d => Math.Cosh(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue deg(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "deg", d => d * 180.0 / Math.PI); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue exp(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "exp", d => Math.Exp(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue floor(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "floor", d => Math.Floor(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue fmod(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec2(args, "fmod", (d1, d2) => Math.IEEERemainder(d1, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue frexp(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
// http://stackoverflow.com/questions/389993/extracting-mantissa-and-exponent-from-double-in-c-sharp |
||||||
|
|
||||||
|
DynValue arg = args.AsType(0, "frexp", DataType.Number, false); |
||||||
|
|
||||||
|
double d = arg.Number; |
||||||
|
|
||||||
|
// Translate the double into sign, exponent and mantissa. |
||||||
|
long bits = BitConverter.DoubleToInt64Bits(d); |
||||||
|
// Note that the shift is sign-extended, hence the test against -1 not 1 |
||||||
|
bool negative = (bits < 0); |
||||||
|
int exponent = (int) ((bits >> 52) & 0x7ffL); |
||||||
|
long mantissa = bits & 0xfffffffffffffL; |
||||||
|
|
||||||
|
// Subnormal numbers; exponent is effectively one higher, |
||||||
|
// but there's no extra normalisation bit in the mantissa |
||||||
|
if (exponent==0) |
||||||
|
{ |
||||||
|
exponent++; |
||||||
|
} |
||||||
|
// Normal numbers; leave exponent as it is but add extra |
||||||
|
// bit to the front of the mantissa |
||||||
|
else |
||||||
|
{ |
||||||
|
mantissa = mantissa | (1L<<52); |
||||||
|
} |
||||||
|
|
||||||
|
// Bias the exponent. It's actually biased by 1023, but we're |
||||||
|
// treating the mantissa as m.0 rather than 0.m, so we need |
||||||
|
// to subtract another 52 from it. |
||||||
|
exponent -= 1075; |
||||||
|
|
||||||
|
if (mantissa == 0) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.NewNumber(0), DynValue.NewNumber(0)); |
||||||
|
} |
||||||
|
|
||||||
|
/* Normalize */ |
||||||
|
while((mantissa & 1) == 0) |
||||||
|
{ /* i.e., Mantissa is even */ |
||||||
|
mantissa >>= 1; |
||||||
|
exponent++; |
||||||
|
} |
||||||
|
|
||||||
|
double m = (double)mantissa; |
||||||
|
double e = (double)exponent; |
||||||
|
while( m >= 1 ) |
||||||
|
{ |
||||||
|
m /= 2.0; |
||||||
|
e += 1.0; |
||||||
|
} |
||||||
|
|
||||||
|
if( negative ) m = -m; |
||||||
|
|
||||||
|
return DynValue.NewTuple(DynValue.NewNumber(m), DynValue.NewNumber(e)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue ldexp(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec2(args, "ldexp", (d1, d2) => d1 * Math.Pow(2, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue log(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec2n(args, "log", Math.E, (d1, d2) => Math.Log(d1, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue max(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return execaccum(args, "max", (d1, d2) => Math.Max(d1, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue min(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return execaccum(args, "min", (d1, d2) => Math.Min(d1, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue modf(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue arg = args.AsType(0, "modf", DataType.Number, false); |
||||||
|
return DynValue.NewTuple(DynValue.NewNumber(Math.Floor(arg.Number)), DynValue.NewNumber(arg.Number - Math.Floor(arg.Number))); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue pow(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec2(args, "pow", (d1, d2) => Math.Pow(d1, d2)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rad(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "rad", d => d * Math.PI / 180.0); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue random(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue m = args.AsType(0, "random", DataType.Number, true); |
||||||
|
DynValue n = args.AsType(1, "random", DataType.Number, true); |
||||||
|
Random R = GetRandom(executionContext.GetScript()); |
||||||
|
double d; |
||||||
|
|
||||||
|
if (m.IsNil() && n.IsNil()) |
||||||
|
{ |
||||||
|
d = R.NextDouble(); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
int a = n.IsNil() ? 1 : (int)n.Number; |
||||||
|
int b = (int)m.Number; |
||||||
|
|
||||||
|
if (a < b) |
||||||
|
d = R.Next(a, b + 1); |
||||||
|
else |
||||||
|
d = R.Next(b, a + 1); |
||||||
|
} |
||||||
|
|
||||||
|
return DynValue.NewNumber(d); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue randomseed(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue arg = args.AsType(0, "randomseed", DataType.Number, false); |
||||||
|
var script = executionContext.GetScript(); |
||||||
|
SetRandom(script, new Random((int)arg.Number)); |
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue sin(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "sin", d => Math.Sin(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue sinh(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "sinh", d => Math.Sinh(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue sqrt(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "sqrt", d => Math.Sqrt(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue tan(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "tan", d => Math.Tan(d)); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue tanh(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return exec1(args, "tanh", d => Math.Tanh(d)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 38103786f8d984326b5123cab6ca4b47 |
||||||
|
timeCreated: 1475786653 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,122 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing metatable related Lua functions (xxxmetatable and rawxxx). |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule] |
||||||
|
public class MetaTableModule |
||||||
|
{ |
||||||
|
// setmetatable (table, metatable) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// Sets the metatable for the given table. (You cannot change the metatable of other |
||||||
|
// types from Lua, only from C.) If metatable is nil, removes the metatable of the given table. |
||||||
|
// If the original metatable has a "__metatable" field, raises an error ("cannot change a protected metatable"). |
||||||
|
// This function returns table. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue setmetatable(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args.AsType(0, "setmetatable", DataType.Table); |
||||||
|
DynValue metatable = args.AsType(1, "setmetatable", DataType.Table, true); |
||||||
|
|
||||||
|
DynValue curmeta = executionContext.GetMetamethod(table, "__metatable"); |
||||||
|
|
||||||
|
if (curmeta != null) |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException("cannot change a protected metatable"); |
||||||
|
} |
||||||
|
|
||||||
|
table.Table.MetaTable = metatable.Table; |
||||||
|
return table; |
||||||
|
} |
||||||
|
|
||||||
|
// getmetatable (object) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// If object does not have a metatable, returns nil. Otherwise, if the object's metatable |
||||||
|
// has a "__metatable" field, returns the associated value. Otherwise, returns the metatable of the given object. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue getmetatable(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue obj = args[0]; |
||||||
|
Table meta = null; |
||||||
|
|
||||||
|
if (obj.Type.CanHaveTypeMetatables()) |
||||||
|
{ |
||||||
|
meta = executionContext.GetScript().GetTypeMetatable(obj.Type); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if (obj.Type == DataType.Table) |
||||||
|
{ |
||||||
|
meta = obj.Table.MetaTable; |
||||||
|
} |
||||||
|
|
||||||
|
if (meta == null) |
||||||
|
return DynValue.Nil; |
||||||
|
else if (meta.RawGet("__metatable") != null) |
||||||
|
return meta.Get("__metatable"); |
||||||
|
else |
||||||
|
return DynValue.NewTable(meta); |
||||||
|
} |
||||||
|
|
||||||
|
// rawget (table, index) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// Gets the real value of table[index], without invoking any metamethod. table must be a table; index may be any value. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rawget(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args.AsType(0, "rawget", DataType.Table); |
||||||
|
DynValue index = args[1]; |
||||||
|
|
||||||
|
return table.Table.Get(index); |
||||||
|
} |
||||||
|
|
||||||
|
// rawset (table, index, value) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// Sets the real value of table[index] to value, without invoking any metamethod. table must be a table, |
||||||
|
// index any value different from nil and NaN, and value any Lua value. |
||||||
|
// This function returns table. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rawset(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args.AsType(0, "rawset", DataType.Table); |
||||||
|
DynValue index = args[1]; |
||||||
|
|
||||||
|
table.Table.Set(index, args[2]); |
||||||
|
|
||||||
|
return table; |
||||||
|
} |
||||||
|
|
||||||
|
// rawequal (v1, v2) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// Checks whether v1 is equal to v2, without invoking any metamethod. Returns a boolean. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rawequal(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v1 = args[0]; |
||||||
|
DynValue v2 = args[1]; |
||||||
|
|
||||||
|
return DynValue.NewBoolean(v1.Equals(v2)); |
||||||
|
} |
||||||
|
|
||||||
|
//rawlen (v) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
//Returns the length of the object v, which must be a table or a string, without invoking any metamethod. Returns an integer number. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rawlen(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
if (args[0].Type != DataType.String && args[0].Type != DataType.Table) |
||||||
|
{ |
||||||
|
throw ScriptRuntimeException.BadArgument(0, "rawlen", "table or string", args[0].Type.ToErrorTypeString(), false); |
||||||
|
} |
||||||
|
|
||||||
|
return args[0].GetLength(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: b3b971ba440d24e91a6ff0bc9e306d59 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,132 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing system related Lua functions from the 'os' module. |
||||||
|
/// Proper support requires a compatible IPlatformAccessor |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "os")] |
||||||
|
public class OsSystemModule |
||||||
|
{ |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue execute(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v = args.AsType(0, "execute", DataType.String, true); |
||||||
|
|
||||||
|
if (v.IsNil()) |
||||||
|
{ |
||||||
|
return DynValue.NewBoolean(true); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
int exitCode = Script.GlobalOptions.Platform.OS_Execute(v.String); |
||||||
|
|
||||||
|
return DynValue.NewTuple( |
||||||
|
DynValue.Nil, |
||||||
|
DynValue.NewString("exit"), |
||||||
|
DynValue.NewNumber(exitCode)); |
||||||
|
} |
||||||
|
catch (Exception) |
||||||
|
{ |
||||||
|
// +++ bad to swallow.. |
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue exit(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue v_exitCode = args.AsType(0, "exit", DataType.Number, true); |
||||||
|
int exitCode = 0; |
||||||
|
|
||||||
|
if (v_exitCode.IsNotNil()) |
||||||
|
exitCode = (int)v_exitCode.Number; |
||||||
|
|
||||||
|
Script.GlobalOptions.Platform.OS_ExitFast(exitCode); |
||||||
|
|
||||||
|
throw new InvalidOperationException("Unreachable code.. reached."); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue getenv(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue varName = args.AsType(0, "getenv", DataType.String, false); |
||||||
|
|
||||||
|
string val = Script.GlobalOptions.Platform.GetEnvironmentVariable(varName.String); |
||||||
|
|
||||||
|
if (val == null) |
||||||
|
return DynValue.Nil; |
||||||
|
else |
||||||
|
return DynValue.NewString(val); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue remove(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
string fileName = args.AsType(0, "remove", DataType.String, false).String; |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
if (Script.GlobalOptions.Platform.OS_FileExists(fileName)) |
||||||
|
{ |
||||||
|
Script.GlobalOptions.Platform.OS_FileDelete(fileName); |
||||||
|
return DynValue.True; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return DynValue.NewTuple( |
||||||
|
DynValue.Nil, |
||||||
|
DynValue.NewString("{0}: No such file or directory.", fileName), |
||||||
|
DynValue.NewNumber(-1)); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.Message), DynValue.NewNumber(-1)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue rename(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
string fileNameOld = args.AsType(0, "rename", DataType.String, false).String; |
||||||
|
string fileNameNew = args.AsType(1, "rename", DataType.String, false).String; |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
if (!Script.GlobalOptions.Platform.OS_FileExists(fileNameOld)) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, |
||||||
|
DynValue.NewString("{0}: No such file or directory.", fileNameOld), |
||||||
|
DynValue.NewNumber(-1)); |
||||||
|
} |
||||||
|
|
||||||
|
Script.GlobalOptions.Platform.OS_FileMove(fileNameOld, fileNameNew); |
||||||
|
return DynValue.True; |
||||||
|
} |
||||||
|
catch (Exception ex) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.Nil, DynValue.NewString(ex.Message), DynValue.NewNumber(-1)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue setlocale(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewString("n/a"); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue tmpname(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return DynValue.NewString(Script.GlobalOptions.Platform.IO_OS_GetTempFilename()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 1bb7798955cba48c6b0e19cf3daa219f |
||||||
|
timeCreated: 1475786653 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,287 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Text; |
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing time related Lua functions from the 'os' module. |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule(Namespace = "os")] |
||||||
|
public class OsTimeModule |
||||||
|
{ |
||||||
|
static DateTime Time0 = DateTime.UtcNow; |
||||||
|
static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); |
||||||
|
|
||||||
|
private static DynValue GetUnixTime(DateTime dateTime, DateTime? epoch = null) |
||||||
|
{ |
||||||
|
double time = (dateTime - (epoch ?? Epoch)).TotalSeconds; |
||||||
|
|
||||||
|
if (time < 0.0) |
||||||
|
return DynValue.Nil; |
||||||
|
|
||||||
|
return DynValue.NewNumber(time); |
||||||
|
} |
||||||
|
|
||||||
|
private static DateTime FromUnixTime(double unixtime) |
||||||
|
{ |
||||||
|
TimeSpan ts = TimeSpan.FromSeconds(unixtime); |
||||||
|
return Epoch + ts; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue clock(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
return GetUnixTime(DateTime.UtcNow, Time0); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue difftime(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue t2 = args.AsType(0, "difftime", DataType.Number, false); |
||||||
|
DynValue t1 = args.AsType(1, "difftime", DataType.Number, true); |
||||||
|
|
||||||
|
if (t1.IsNil()) |
||||||
|
return DynValue.NewNumber(t2.Number); |
||||||
|
|
||||||
|
return DynValue.NewNumber(t2.Number - t1.Number); |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue time(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DateTime date = DateTime.UtcNow; |
||||||
|
|
||||||
|
if (args.Count > 0) |
||||||
|
{ |
||||||
|
DynValue vt = args.AsType(0, "time", DataType.Table, true); |
||||||
|
if (vt.Type == DataType.Table) |
||||||
|
date = ParseTimeTable(vt.Table); |
||||||
|
} |
||||||
|
|
||||||
|
return GetUnixTime(date); |
||||||
|
} |
||||||
|
|
||||||
|
static DateTime ParseTimeTable(Table t) |
||||||
|
{ |
||||||
|
int sec = GetTimeTableField(t, "sec") ?? 0; |
||||||
|
int min = GetTimeTableField(t, "min") ?? 0; |
||||||
|
int hour = GetTimeTableField(t, "hour") ?? 12; |
||||||
|
int? day = GetTimeTableField(t, "day"); |
||||||
|
int? month = GetTimeTableField(t, "month"); |
||||||
|
int? year = GetTimeTableField(t, "year"); |
||||||
|
|
||||||
|
if (day == null) |
||||||
|
throw new ScriptRuntimeException("field 'day' missing in date table"); |
||||||
|
|
||||||
|
if (month == null) |
||||||
|
throw new ScriptRuntimeException("field 'month' missing in date table"); |
||||||
|
|
||||||
|
if (year == null) |
||||||
|
throw new ScriptRuntimeException("field 'year' missing in date table"); |
||||||
|
|
||||||
|
return new DateTime(year.Value, month.Value, day.Value, hour, min, sec); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static int? GetTimeTableField(Table t, string key) |
||||||
|
{ |
||||||
|
DynValue v = t.Get(key); |
||||||
|
double? d = v.CastToNumber(); |
||||||
|
|
||||||
|
if (d.HasValue) |
||||||
|
return (int)d.Value; |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue date(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DateTime reference = DateTime.UtcNow; |
||||||
|
|
||||||
|
DynValue vformat = args.AsType(0, "date", DataType.String, true); |
||||||
|
DynValue vtime = args.AsType(1, "date", DataType.Number, true); |
||||||
|
|
||||||
|
string format = (vformat.IsNil()) ? "%c" : vformat.String; |
||||||
|
|
||||||
|
if (vtime.IsNotNil()) |
||||||
|
reference = FromUnixTime(vtime.Number); |
||||||
|
|
||||||
|
bool isDst = false; |
||||||
|
|
||||||
|
if (format.StartsWith("!")) |
||||||
|
{ |
||||||
|
format = format.Substring(1); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
#if !(PCL || ENABLE_DOTNET || NETFX_CORE) |
||||||
|
|
||||||
|
try |
||||||
|
{ |
||||||
|
reference = TimeZoneInfo.ConvertTimeFromUtc(reference, TimeZoneInfo.Local); |
||||||
|
isDst = reference.IsDaylightSavingTime(); |
||||||
|
} |
||||||
|
catch (TimeZoneNotFoundException) |
||||||
|
{ |
||||||
|
// this catches a weird mono bug: https://bugzilla.xamarin.com/show_bug.cgi?id=11817 |
||||||
|
// however the behavior is definitely not correct. damn. |
||||||
|
} |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
if (format == "*t") |
||||||
|
{ |
||||||
|
Table t = new Table(executionContext.GetScript()); |
||||||
|
|
||||||
|
t.Set("year", DynValue.NewNumber(reference.Year)); |
||||||
|
t.Set("month", DynValue.NewNumber(reference.Month)); |
||||||
|
t.Set("day", DynValue.NewNumber(reference.Day)); |
||||||
|
t.Set("hour", DynValue.NewNumber(reference.Hour)); |
||||||
|
t.Set("min", DynValue.NewNumber(reference.Minute)); |
||||||
|
t.Set("sec", DynValue.NewNumber(reference.Second)); |
||||||
|
t.Set("wday", DynValue.NewNumber(((int)reference.DayOfWeek) + 1)); |
||||||
|
t.Set("yday", DynValue.NewNumber(reference.DayOfYear)); |
||||||
|
t.Set("isdst", DynValue.NewBoolean(isDst)); |
||||||
|
|
||||||
|
return DynValue.NewTable(t); |
||||||
|
} |
||||||
|
|
||||||
|
else return DynValue.NewString(StrFTime(format, reference)); |
||||||
|
} |
||||||
|
|
||||||
|
private static string StrFTime(string format, DateTime d) |
||||||
|
{ |
||||||
|
// ref: http://www.cplusplus.com/reference/ctime/strftime/ |
||||||
|
|
||||||
|
Dictionary<char, string> STANDARD_PATTERNS = new Dictionary<char, string>() |
||||||
|
{ |
||||||
|
{ 'a', "ddd" }, |
||||||
|
{ 'A', "dddd" }, |
||||||
|
{ 'b', "MMM" }, |
||||||
|
{ 'B', "MMMM" }, |
||||||
|
{ 'c', "f" }, |
||||||
|
{ 'd', "dd" }, |
||||||
|
{ 'D', "MM/dd/yy" }, |
||||||
|
{ 'F', "yyyy-MM-dd" }, |
||||||
|
{ 'g', "yy" }, |
||||||
|
{ 'G', "yyyy" }, |
||||||
|
{ 'h', "MMM" }, |
||||||
|
{ 'H', "HH" }, |
||||||
|
{ 'I', "hh" }, |
||||||
|
{ 'm', "MM" }, |
||||||
|
{ 'M', "mm" }, |
||||||
|
{ 'p', "tt" }, |
||||||
|
{ 'r', "h:mm:ss tt" }, |
||||||
|
{ 'R', "HH:mm" }, |
||||||
|
{ 'S', "ss" }, |
||||||
|
{ 'T', "HH:mm:ss" }, |
||||||
|
{ 'y', "yy" }, |
||||||
|
{ 'Y', "yyyy" }, |
||||||
|
{ 'x', "d" }, |
||||||
|
{ 'X', "T" }, |
||||||
|
{ 'z', "zzz" }, |
||||||
|
{ 'Z', "zzz" }, |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
|
||||||
|
bool isEscapeSequence = false; |
||||||
|
|
||||||
|
for (int i = 0; i < format.Length; i++) |
||||||
|
{ |
||||||
|
char c = format[i]; |
||||||
|
|
||||||
|
if (c == '%') |
||||||
|
{ |
||||||
|
if (isEscapeSequence) |
||||||
|
{ |
||||||
|
sb.Append('%'); |
||||||
|
isEscapeSequence = false; |
||||||
|
} |
||||||
|
else |
||||||
|
isEscapeSequence = true; |
||||||
|
|
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (!isEscapeSequence) |
||||||
|
{ |
||||||
|
sb.Append(c); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
if (c == 'O' || c == 'E') continue; // no modifiers |
||||||
|
|
||||||
|
isEscapeSequence = false; |
||||||
|
|
||||||
|
if (STANDARD_PATTERNS.ContainsKey(c)) |
||||||
|
{ |
||||||
|
sb.Append(d.ToString(STANDARD_PATTERNS[c])); |
||||||
|
} |
||||||
|
else if (c == 'e') |
||||||
|
{ |
||||||
|
string s = d.ToString("%d"); |
||||||
|
if (s.Length < 2) s = " " + s; |
||||||
|
sb.Append(s); |
||||||
|
} |
||||||
|
else if (c == 'n') |
||||||
|
{ |
||||||
|
sb.Append('\n'); |
||||||
|
} |
||||||
|
else if (c == 't') |
||||||
|
{ |
||||||
|
sb.Append('\t'); |
||||||
|
} |
||||||
|
else if (c == 'C') |
||||||
|
{ |
||||||
|
sb.Append((int)(d.Year / 100)); |
||||||
|
} |
||||||
|
else if (c == 'j') |
||||||
|
{ |
||||||
|
sb.Append(d.DayOfYear.ToString("000")); |
||||||
|
} |
||||||
|
else if (c == 'u') |
||||||
|
{ |
||||||
|
int weekDay = (int)d.DayOfWeek; |
||||||
|
if (weekDay == 0) |
||||||
|
weekDay = 7; |
||||||
|
|
||||||
|
sb.Append(weekDay); |
||||||
|
} |
||||||
|
else if (c == 'w') |
||||||
|
{ |
||||||
|
int weekDay = (int)d.DayOfWeek; |
||||||
|
sb.Append(weekDay); |
||||||
|
} |
||||||
|
else if (c == 'U') |
||||||
|
{ |
||||||
|
// Week number with the first Sunday as the first day of week one (00-53) |
||||||
|
sb.Append("??"); |
||||||
|
} |
||||||
|
else if (c == 'V') |
||||||
|
{ |
||||||
|
// ISO 8601 week number (00-53) |
||||||
|
sb.Append("??"); |
||||||
|
} |
||||||
|
else if (c == 'W') |
||||||
|
{ |
||||||
|
// Week number with the first Monday as the first day of week one (00-53) |
||||||
|
sb.Append("??"); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
throw new ScriptRuntimeException("bad argument #1 to 'date' (invalid conversion specifier '{0}')", format); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return sb.ToString(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 29679b67516094990a23d5066e7af0ea |
||||||
|
timeCreated: 1476432879 |
||||||
|
licenseType: Free |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,9 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: a18a955a013284f08b443c601f5b9612 |
||||||
|
folderAsset: yes |
||||||
|
timeCreated: 1475786652 |
||||||
|
licenseType: Pro |
||||||
|
DefaultImporter: |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,998 @@ |
|||||||
|
// 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 = 200; |
||||||
|
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); |
||||||
|
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"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: d921f217918ee4c0e97d5ad218c273ab |
||||||
|
timeCreated: 1475786656 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,56 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib.StringLib |
||||||
|
{ |
||||||
|
internal class StringRange |
||||||
|
{ |
||||||
|
public int Start { get; set; } |
||||||
|
public int End { get; set; } |
||||||
|
|
||||||
|
public StringRange() |
||||||
|
{ |
||||||
|
Start = 0; |
||||||
|
End = 0; |
||||||
|
} |
||||||
|
|
||||||
|
public StringRange(int start, int end) |
||||||
|
{ |
||||||
|
Start = start; |
||||||
|
End = end; |
||||||
|
} |
||||||
|
|
||||||
|
public static StringRange FromLuaRange(DynValue start, DynValue end, int? defaultEnd = null) |
||||||
|
{ |
||||||
|
int i = start.IsNil() ? 1 : (int)start.Number; |
||||||
|
int j = end.IsNil() ? (defaultEnd ?? i) : (int)end.Number; |
||||||
|
|
||||||
|
return new StringRange(i, j); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Returns the substring of s that starts at i and continues until j; i and j can be negative. |
||||||
|
// If, after the translation of negative indices, i is less than 1, it is corrected to 1. |
||||||
|
// If j is greater than the string length, it is corrected to that length. |
||||||
|
// If, after these corrections, i is greater than j, the function returns the empty string. |
||||||
|
public string ApplyToString(string value) |
||||||
|
{ |
||||||
|
int i = Start < 0 ? Start + value.Length + 1 : Start; |
||||||
|
int j = End < 0 ? End + value.Length + 1 : End; |
||||||
|
|
||||||
|
if (i < 1) i = 1; |
||||||
|
if (j > value.Length) j = value.Length; |
||||||
|
|
||||||
|
if (i > j) |
||||||
|
return string.Empty; |
||||||
|
|
||||||
|
return value.Substring(i - 1, j - i + 1); |
||||||
|
} |
||||||
|
|
||||||
|
public int Length() |
||||||
|
{ |
||||||
|
return (End - Start) + 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: 155a3aa6f6abc4dd5b920c33c2151dab |
||||||
|
timeCreated: 1475786653 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,298 @@ |
|||||||
|
// 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 |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing string Lua functions |
||||||
|
/// </summary> |
||||||
|
[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<int, int> 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)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
fileFormatVersion: 2 |
||||||
|
guid: b3eb3848b53e142a483d14eb6b5b0484 |
||||||
|
timeCreated: 1475786655 |
||||||
|
licenseType: Pro |
||||||
|
MonoImporter: |
||||||
|
serializedVersion: 2 |
||||||
|
defaultReferences: [] |
||||||
|
executionOrder: 0 |
||||||
|
icon: {instanceID: 0} |
||||||
|
userData: |
||||||
|
assetBundleName: |
||||||
|
assetBundleVariant: |
@ -0,0 +1,92 @@ |
|||||||
|
// Disable warnings about XML documentation |
||||||
|
#pragma warning disable 1591 |
||||||
|
|
||||||
|
|
||||||
|
namespace MoonSharp.Interpreter.CoreLib |
||||||
|
{ |
||||||
|
/// <summary> |
||||||
|
/// Class implementing table Lua iterators (pairs, ipairs, next) |
||||||
|
/// </summary> |
||||||
|
[MoonSharpModule] |
||||||
|
public class TableIteratorsModule |
||||||
|
{ |
||||||
|
// ipairs (t) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// If t has a metamethod __ipairs, calls it with t as argument and returns the first three results from the call. |
||||||
|
// Otherwise, returns three values: an iterator function, the table t, and 0, so that the construction |
||||||
|
// for i,v in ipairs(t) do body end |
||||||
|
// will iterate over the pairs (1,t[1]), (2,t[2]), ..., up to the first integer key absent from the table. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue ipairs(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args[0]; |
||||||
|
|
||||||
|
DynValue meta = executionContext.GetMetamethodTailCall(table, "__ipairs", args.GetArray()); |
||||||
|
|
||||||
|
return meta ?? DynValue.NewTuple(DynValue.NewCallback(__next_i), table, DynValue.NewNumber(0)); |
||||||
|
} |
||||||
|
|
||||||
|
// pairs (t) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// If t has a metamethod __pairs, calls it with t as argument and returns the first three results from the call. |
||||||
|
// Otherwise, returns three values: the next function, the table t, and nil, so that the construction |
||||||
|
// for k,v in pairs(t) do body end |
||||||
|
// will iterate over all key–value pairs of table t. |
||||||
|
// See function next for the caveats of modifying the table during its traversal. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue pairs(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args[0]; |
||||||
|
|
||||||
|
DynValue meta = executionContext.GetMetamethodTailCall(table, "__pairs", args.GetArray()); |
||||||
|
|
||||||
|
return meta ?? DynValue.NewTuple(DynValue.NewCallback(next), table); |
||||||
|
} |
||||||
|
|
||||||
|
// next (table [, index]) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// Allows a program to traverse all fields of a table. Its first argument is a table and its second argument is an |
||||||
|
// index in this table. next returns the next index of the table and its associated value. |
||||||
|
// When called with nil as its second argument, next returns an initial index and its associated value. |
||||||
|
// When called with the last index, or with nil in an empty table, next returns nil. If the second argument is absent, |
||||||
|
// then it is interpreted as nil. In particular, you can use next(t) to check whether a table is empty. |
||||||
|
// The order in which the indices are enumerated is not specified, even for numeric indices. |
||||||
|
// (To traverse a table in numeric order, use a numerical for.) |
||||||
|
// The behavior of next is undefined if, during the traversal, you assign any value to a non-existent field in the table. |
||||||
|
// You may however modify existing fields. In particular, you may clear existing fields. |
||||||
|
[MoonSharpModuleMethod] |
||||||
|
public static DynValue next(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args.AsType(0, "next", DataType.Table); |
||||||
|
DynValue index = args[1]; |
||||||
|
|
||||||
|
TablePair? pair = table.Table.NextKey(index); |
||||||
|
|
||||||
|
if (pair.HasValue) |
||||||
|
return DynValue.NewTuple(pair.Value.Key, pair.Value.Value); |
||||||
|
else |
||||||
|
throw new ScriptRuntimeException("invalid key to 'next'"); |
||||||
|
} |
||||||
|
|
||||||
|
// __next_i (table [, index]) |
||||||
|
// ------------------------------------------------------------------------------------------------------------------- |
||||||
|
// Allows a program to traverse all fields of an array. index is an integer number |
||||||
|
public static DynValue __next_i(ScriptExecutionContext executionContext, CallbackArguments args) |
||||||
|
{ |
||||||
|
DynValue table = args.AsType(0, "!!next_i!!", DataType.Table); |
||||||
|
DynValue index = args.AsType(1, "!!next_i!!", DataType.Number); |
||||||
|
|
||||||
|
int idx = ((int)index.Number) + 1; |
||||||
|
DynValue val = table.Table.Get(idx); |
||||||
|
|
||||||
|
if (val.Type != DataType.Nil) |
||||||
|
{ |
||||||
|
return DynValue.NewTuple(DynValue.NewNumber(idx), val); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
return DynValue.Nil; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue