Skip to content

Commit

Permalink
Stack trace debugger for desktop only
Browse files Browse the repository at this point in the history
  • Loading branch information
neolithos committed May 9, 2015
1 parent 9e49288 commit 701ca3e
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 150 deletions.
3 changes: 2 additions & 1 deletion NeoCmd/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ private enum Commands
private sealed class LuaCommandGlobal : LuaGlobal
{
public LuaCommandGlobal(Lua lua)
:base(lua)
: base(lua)
{
this.LuaPackage.path += ";" + LuaLibraryPackage.ExecutingDirectoryPathVariable;
} // ctor

[LuaMember("read")]
Expand Down
4 changes: 2 additions & 2 deletions NeoLua/LuaEmit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1507,8 +1507,8 @@ public static Expression SetMember(Lua runtime, Expression instance, Type type,

if (members == null || members.Length == 0)
throw new LuaEmitException(LuaEmitException.MemberNotFound, type.Name, sMemberName);
else if (members.Length > 1)
throw new LuaEmitException(LuaEmitException.MemberNotUnique, type.Name, sMemberName);
//else if (members.Length > 1)
// throw new LuaEmitException(LuaEmitException.MemberNotUnique, type.Name, sMemberName);
else
{
if (members[0] is PropertyInfo)
Expand Down
150 changes: 150 additions & 0 deletions NeoLuaD/Lua.Libraries.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,159 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;

namespace Neo.IronLua
{
#region -- class LuaLibraryPackage ------------------------------------------------

///////////////////////////////////////////////////////////////////////////////
/// <summary></summary>
public sealed class LuaLibraryPackage
{
/// <summary></summary>
public const string CurrentDirectoryPathVariable = "%currentdirectory%";
/// <summary></summary>
public const string ExecutingDirectoryPathVariable = "%executingdirectory%";

#region -- class LuaLoadedTable ---------------------------------------------------

private class LuaLoadedTable : LuaTable
{
private LuaGlobal global;

public LuaLoadedTable(LuaGlobal global)
{
this.global = global;
} // ctor

protected override object OnIndex(object key)
{
object value;
if (global.loaded != null && global.loaded.TryGetValue(key, out value))
return value;
return base.OnIndex(key);
} // func OnIndex
} // class LuaLoadedTable

#endregion

private object packageLock = new object();
private Dictionary<string, WeakReference> loadedModuls = null;

private string[] paths;
private LuaCompileOptions compileOptions = null;

public LuaLibraryPackage(LuaGlobal global)
{
this.loaded = new LuaLoadedTable(global);
this.path = CurrentDirectoryPathVariable;
} // ctor

internal LuaChunk LuaRequire(LuaGlobal global, string sModName)
{
if (String.IsNullOrEmpty(sModName))
return null;

string sFileName;
DateTime dtStamp;
if (LuaRequireFindFile(sModName, out sFileName, out dtStamp))
{
lock (packageLock)
{
WeakReference rc;
LuaChunk c;
string sCacheId = sFileName + ";" + dtStamp.ToString("o");

// is the modul loaded
if (loadedModuls == null ||
!loadedModuls.TryGetValue(sCacheId, out rc) ||
!rc.IsAlive)
{
// compile the modul
c = global.Lua.CompileChunk(sFileName, compileOptions);

// Update Cache
if (loadedModuls == null)
loadedModuls = new Dictionary<string, WeakReference>();
loadedModuls[sCacheId] = new WeakReference(c);
}
else
c = (LuaChunk)rc.Target;

return c;
}
}
else
return null;
} // func LuaRequire

private bool LuaRequireCheckFile(ref string sFileName, ref DateTime dtStamp)
{
try
{
// replace variables
if (sFileName.Contains(CurrentDirectoryPathVariable))
sFileName = sFileName.Replace(CurrentDirectoryPathVariable, Environment.CurrentDirectory);
if (sFileName.Contains(ExecutingDirectoryPathVariable))
sFileName = sFileName.Replace(ExecutingDirectoryPathVariable, System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

// check if the file exists
if (!File.Exists(sFileName))
return false;

// get the time stamp
dtStamp = File.GetLastWriteTime(sFileName);
return true;
}
catch (IOException)
{
return false;
}
} // func LuaRequireCheckFile

internal bool LuaRequireFindFile(string sModName, out string sFileName, out DateTime dtStamp)
{
dtStamp = DateTime.MinValue;
sFileName = null;

foreach (string c in paths)
{
if (String.IsNullOrEmpty(c))
continue;
else
{
sFileName = System.IO.Path.Combine(c, sModName + ".lua");
return LuaRequireCheckFile(ref sFileName, ref dtStamp);
}
}

return false;
} // func LuaRequireFindFile

public LuaTable loaded { get; private set; }
public string path
{
get
{
return String.Join(";", paths);
}
set
{
if (String.IsNullOrEmpty(value))
paths = null;
else
paths = value.Split(';');
}
} // prop Path

public string[] Path { get { return paths; } }
public LuaCompileOptions CompileOptions { get { return compileOptions; } set { compileOptions = value; } }
} // class LuaLibraryPackage

#endregion

#region -- Operating System Facilities ----------------------------------------------

///////////////////////////////////////////////////////////////////////////////
Expand Down
148 changes: 1 addition & 147 deletions NeoLuaD/LuaGlobal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,155 +12,9 @@ namespace Neo.IronLua
/// <summary></summary>
public class LuaGlobal : LuaGlobalPortable
{
/// <summary></summary>
public const string CurrentDirectoryPathVariable = "%currentdirectory%";
/// <summary></summary>
public const string ExecutingDirectoryPathVariable = "%executingdirectory%";

#region -- class LuaLoadedTable ---------------------------------------------------

private class LuaLoadedTable : LuaTable
{
private LuaGlobal global;

public LuaLoadedTable(LuaGlobal global)
{
this.global = global;
} // ctor

protected override object OnIndex(object key)
{
object value;
if (global.loaded != null && global.loaded.TryGetValue(key, out value))
return value;
return base.OnIndex(key);
} // func OnIndex
} // class LuaLoadedTable

#endregion

#region -- class LuaLibraryPackage ------------------------------------------------

internal sealed class LuaLibraryPackage
{
private object packageLock = new object();
private Dictionary<string, WeakReference> loadedModuls = null;

private string[] paths;
private LuaCompileOptions compileOptions = null;

public LuaLibraryPackage(LuaGlobal global)
{
this.loaded = new LuaLoadedTable(global);
this.path = CurrentDirectoryPathVariable;
} // ctor

internal LuaChunk LuaRequire(LuaGlobal global, string sModName)
{
if (String.IsNullOrEmpty(sModName))
return null;

string sFileName;
DateTime dtStamp;
if (LuaRequireFindFile(sModName, out sFileName, out dtStamp))
{
lock (packageLock)
{
WeakReference rc;
LuaChunk c;
string sCacheId = sFileName + ";" + dtStamp.ToString("o");

// is the modul loaded
if (loadedModuls == null ||
!loadedModuls.TryGetValue(sCacheId, out rc) ||
!rc.IsAlive)
{
// compile the modul
c = global.Lua.CompileChunk(sFileName, compileOptions);

// Update Cache
if (loadedModuls == null)
loadedModuls = new Dictionary<string, WeakReference>();
loadedModuls[sCacheId] = new WeakReference(c);
}
else
c = (LuaChunk)rc.Target;

return c;
}
}
else
return null;
} // func LuaRequire

private bool LuaRequireCheckFile(ref string sFileName, ref DateTime dtStamp)
{
try
{
// replace variables
if (sFileName.Contains(CurrentDirectoryPathVariable))
sFileName = sFileName.Replace(CurrentDirectoryPathVariable, Environment.CurrentDirectory);
if (sFileName.Contains(ExecutingDirectoryPathVariable))
sFileName = sFileName.Replace(ExecutingDirectoryPathVariable, System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));

// check if the file exists
if (!File.Exists(sFileName))
return false;

// get the time stamp
dtStamp = File.GetLastWriteTime(sFileName);
return true;
}
catch (IOException)
{
return false;
}
} // func LuaRequireCheckFile

internal bool LuaRequireFindFile(string sModName, out string sFileName, out DateTime dtStamp)
{
dtStamp = DateTime.MinValue;
sFileName = null;

foreach (string c in paths)
{
if (String.IsNullOrEmpty(c))
continue;
else
{
sFileName = System.IO.Path.Combine(c, sModName + ".lua");
return LuaRequireCheckFile(ref sFileName, ref dtStamp);
}
}

return false;
} // func LuaRequireFindFile

public LuaTable loaded { get; private set; }
public string path
{
get
{
return String.Join(";", paths);
}
set
{
if (String.IsNullOrEmpty(value))
paths = null;
else
paths = value.Split(';');
}
} // prop Path

public string[] Path { get { return paths; } }
public LuaCompileOptions CompileOptions { get { return compileOptions; } set { compileOptions = value; } }
} // class LuaLibraryPackage

#endregion

private LuaFilePackage io = null;
private LuaLibraryPackage package = null;
private Dictionary<object, object> loaded = new Dictionary<object, object>();
internal Dictionary<object, object> loaded = new Dictionary<object, object>();

#region -- Ctor/Dtor --------------------------------------------------------------

Expand Down
36 changes: 36 additions & 0 deletions NeoLuaD/LuaStackTraceDebugger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ private struct FieldDefine
private LuaStackTraceDebugger debug;
private TypeBuilder type;

private bool lFirstLambdaDone = false;
private Dictionary<object, FieldDefine> fields;

#region -- Ctor/Dtor ------------------------------------------------------------
Expand Down Expand Up @@ -193,6 +194,33 @@ protected override Expression VisitDynamic(DynamicExpression node)

#endregion

protected override Expression VisitLambda<T>(Expression<T> node)
{
if (!lFirstLambdaDone)
{
lFirstLambdaDone = true;
ParameterExpression exceptionE = Expression.Parameter(typeof(Exception), "e");
return Visit(
Expression.Lambda<T>(
Expression.TryCatch(
node.Body,
Expression.Catch(exceptionE,
Expression.Block(
Expression.Call(LuaExceptionDataGetDataMethodInfo, exceptionE),
Expression.Throw(null, node.Body.Type)
)
)
),
node.Name,
node.TailCall,
node.Parameters
)
);
}
else
return base.VisitLambda<T>(node);
} // func VisitLambda

public void InitMethods(Type typeFinished)
{
foreach (var c in fields)
Expand Down Expand Up @@ -383,6 +411,14 @@ LuaChunk ILuaDebug.CreateChunk(Lua lua, LambdaExpression expr)
private static AssemblyName luaDynamicName = null;
private static ILuaDebug stackTraceDebugger = new LuaStackTraceDebugger();

private static MethodInfo LuaExceptionDataGetDataMethodInfo;

static LuaStackTraceDebugger()
{
var tiLuaExceptionData = typeof(LuaExceptionData).GetTypeInfo();
LuaExceptionDataGetDataMethodInfo = tiLuaExceptionData.FindDeclaredMethod("GetData", ReflectionFlag.Static | ReflectionFlag.NoArguments);
} // ctor

private static AssemblyName GetLuaDynamicName()
{
lock (luaDynamicNameLock)
Expand Down

0 comments on commit 701ca3e

Please sign in to comment.