Skip to content

Commit

Permalink
Added debugger support for closure vars, globals and REPL at various …
Browse files Browse the repository at this point in the history
…stack frames
  • Loading branch information
Benjamin-Dobell committed Oct 27, 2019
1 parent d67daa4 commit a59a238
Show file tree
Hide file tree
Showing 15 changed files with 353 additions and 222 deletions.
6 changes: 5 additions & 1 deletion src/MoonSharp.Interpreter/Debugging/WatchType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ public enum WatchType
/// </summary>
Coroutines,
/// <summary>
/// Topmost local variables
/// Local variables for the current frame.
/// </summary>
Locals,
/// <summary>
/// Closure variables for the current frame.
/// </summary>
Closure,
/// <summary>
/// The list of currently active coroutines
/// </summary>
Threads,
Expand Down
20 changes: 11 additions & 9 deletions src/MoonSharp.Interpreter/Execution/ScriptExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ public class ScriptExecutionContext : IScriptPrivateResource
{
Processor m_Processor;
CallbackFunction m_Callback;
int StackFrameIndex;

internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false)
internal ScriptExecutionContext(Processor p, CallbackFunction callBackFunction, SourceRef sourceRef, bool isDynamic = false, int stackFrameIndex = -1)
{
IsDynamicExecution = isDynamic;
m_Processor = p;
m_Callback = callBackFunction;
CallingLocation = sourceRef;
StackFrameIndex = stackFrameIndex;
}

/// <summary>
Expand All @@ -33,7 +35,7 @@ public bool IsDynamicExecution
}

/// <summary>
/// Gets the location of the code calling back
/// Gets the location of the code calling back
/// </summary>
public SourceRef CallingLocation
{
Expand All @@ -44,14 +46,14 @@ public SourceRef CallingLocation
/// <summary>
/// Gets or sets the additional data associated to this CLR function call.
/// </summary>
public object AdditionalData
public object AdditionalData
{
get { return (m_Callback != null) ? m_Callback.AdditionalData : null; }
set
set
{
if (m_Callback == null) throw new InvalidOperationException("Cannot set additional data on a context which has no callback");
m_Callback.AdditionalData = value;
}
m_Callback.AdditionalData = value;
}
}


Expand Down Expand Up @@ -113,7 +115,7 @@ public Coroutine GetCallingCoroutine()
}

/// <summary>
/// Calls a callback function implemented in "classic way".
/// Calls a callback function implemented in "classic way".
/// Useful to port C code from Lua, or C# code from UniLua and KopiLua.
/// Lua : http://www.lua.org/
/// UniLua : http://github.com/xebecnan/UniLua
Expand Down Expand Up @@ -206,7 +208,7 @@ public DynValue EvaluateSymbol(SymbolRef symref)
if (symref == null)
return DynValue.Nil;

return m_Processor.GetGenericSymbol(symref);
return m_Processor.GetGenericSymbol(symref, StackFrameIndex);
}

/// <summary>
Expand All @@ -222,7 +224,7 @@ public DynValue EvaluateSymbolByName(string symbol)
/// </summary>
public SymbolRef FindSymbolByName(string symbol)
{
return m_Processor.FindSymbolByName(symbol);
return m_Processor.FindSymbolByName(symbol, StackFrameIndex);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,12 +288,14 @@ private void RefreshDebugger(bool hard, int instructionPtr, int stackFrameIndex
List<WatchItem> watches = Debugger_RefreshWatches(context, watchList);
List<WatchItem> vstack = Debugger_RefreshVStack();
List<WatchItem> locals = Debugger_RefreshLocals(stackFrameIndex);
List<WatchItem> closure = Debugger_RefreshClosure(stackFrameIndex);
List<WatchItem> threads = Debugger_RefreshThreads(context);

m_Debug.DebuggerAttached.Update(WatchType.CallStack, callStack, -1);
m_Debug.DebuggerAttached.Update(WatchType.Watches, watches, -1);
m_Debug.DebuggerAttached.Update(WatchType.VStack, vstack, -1);
m_Debug.DebuggerAttached.Update(WatchType.Locals, locals, stackFrameIndex);
m_Debug.DebuggerAttached.Update(WatchType.Closure, closure, stackFrameIndex);
m_Debug.DebuggerAttached.Update(WatchType.Threads, threads, -1);

if (hard)
Expand Down Expand Up @@ -334,27 +336,54 @@ private List<WatchItem> Debugger_RefreshWatches(ScriptExecutionContext context,
private List<WatchItem> Debugger_RefreshLocals(int stackFrameIndex)
{
List<WatchItem> locals = new List<WatchItem>();
var top = m_ExecutionStack.Peek(stackFrameIndex);
var frame = m_ExecutionStack.Peek(stackFrameIndex);

if (top != null && top.Debug_Symbols != null && top.LocalScope != null)
if (frame != null && frame.Debug_Symbols != null && frame.LocalScope != null)
{
int len = Math.Min(top.Debug_Symbols.Length, top.LocalScope.Length);
int len = Math.Min(frame.Debug_Symbols.Length, frame.LocalScope.Length);

for (int i = 0; i < len; i++)
{
locals.Add(new WatchItem()
{
IsError = false,
LValue = top.Debug_Symbols[i],
Value = top.LocalScope[i],
Name = top.Debug_Symbols[i].i_Name
LValue = frame.Debug_Symbols[i],
Value = frame.LocalScope[i],
Name = frame.Debug_Symbols[i].i_Name
});
}
}

return locals;
}

private List<WatchItem> Debugger_RefreshClosure(int stackFrameIndex)
{
List<WatchItem> variables = new List<WatchItem>();
var frame = m_ExecutionStack.Peek(stackFrameIndex);

var closure = frame?.ClosureScope;

if (closure != null)
{
for (int i = 0; i < closure.Symbols.Length; i++)
{
var name = closure.Symbols[i];
var symbolRef = SymbolRef.Upvalue(closure.Symbols[i], i);

variables.Add(new WatchItem()
{
IsError = false,
LValue = symbolRef,
Value = frame.ClosureScope[i],
Name = name
});
}
}

return variables;
}

private WatchItem Debugger_RefreshWatch(ScriptExecutionContext context, DynamicExpression dynExpr)
{
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ private void ClearBlockData(Instruction I)
}


public DynValue GetGenericSymbol(SymbolRef symref)
public DynValue GetGenericSymbol(SymbolRef symref, int stackFrameIndex = -1)
{
switch (symref.i_Type)
{
Expand All @@ -27,9 +27,9 @@ public DynValue GetGenericSymbol(SymbolRef symref)
case SymbolRefType.Global:
return GetGlobalSymbol(GetGenericSymbol(symref.i_Env), symref.i_Name);
case SymbolRefType.Local:
return GetTopNonClrFunction().LocalScope[symref.i_Index];
return GetStackNonClrFunction(stackFrameIndex).LocalScope[symref.i_Index];
case SymbolRefType.Upvalue:
return GetTopNonClrFunction().ClosureScope[symref.i_Index];
return GetStackNonClrFunction(stackFrameIndex).ClosureScope[symref.i_Index];
default:
throw new InternalErrorException("Unexpected {0} LRef at resolution: {1}", symref.i_Type, symref.i_Name);
}
Expand All @@ -52,7 +52,7 @@ private void SetGlobalSymbol(DynValue dynValue, string name, DynValue value)
}


public void AssignGenericSymbol(SymbolRef symref, DynValue value)
public void AssignGenericSymbol(SymbolRef symref, DynValue value, int stackFrameIndex = -1)
{
switch (symref.i_Type)
{
Expand All @@ -61,7 +61,7 @@ public void AssignGenericSymbol(SymbolRef symref, DynValue value)
break;
case SymbolRefType.Local:
{
var stackframe = GetTopNonClrFunction();
var stackframe = GetStackNonClrFunction(stackFrameIndex);

DynValue v = stackframe.LocalScope[symref.i_Index];
if (v == null)
Expand All @@ -72,7 +72,7 @@ public void AssignGenericSymbol(SymbolRef symref, DynValue value)
break;
case SymbolRefType.Upvalue:
{
var stackframe = GetTopNonClrFunction();
var stackframe = GetStackNonClrFunction(stackFrameIndex);

DynValue v = stackframe.ClosureScope[symref.i_Index];
if (v == null)
Expand All @@ -90,8 +90,14 @@ public void AssignGenericSymbol(SymbolRef symref, DynValue value)
}
}

CallStackItem GetTopNonClrFunction()
CallStackItem GetStackNonClrFunction(int stackFrameIndex)
{
if (stackFrameIndex >= 0)
{
var frame = stackFrameIndex < m_ExecutionStack.Count ? m_ExecutionStack.Peek(stackFrameIndex) : null;
return frame?.ClrFunction == null ? frame : null;
}

CallStackItem stackframe = null;

for (int i = 0; i < m_ExecutionStack.Count; i++)
Expand All @@ -106,11 +112,11 @@ CallStackItem GetTopNonClrFunction()
}


public SymbolRef FindSymbolByName(string name)
public SymbolRef FindSymbolByName(string name, int stackFrameIndex = -1)
{
if (m_ExecutionStack.Count > 0)
{
CallStackItem stackframe = GetTopNonClrFunction();
var stackframe = GetStackNonClrFunction(stackFrameIndex);

if (stackframe != null)
{
Expand Down
34 changes: 21 additions & 13 deletions src/MoonSharp.Interpreter/Script.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using MoonSharp.Interpreter.CoreLib;
using MoonSharp.Interpreter.Debugging;
Expand Down Expand Up @@ -87,7 +89,7 @@ public Script(CoreModules coreModules)
public static ScriptOptions DefaultOptions { get; private set; }

/// <summary>
/// Gets access to the script options.
/// Gets access to the script options.
/// </summary>
public ScriptOptions Options { get; private set; }

Expand Down Expand Up @@ -335,10 +337,16 @@ public DynValue DoString(string code, Table globalContext, string codeFriendlyNa

public DynValue DoString(string code, Table globalContext = null)
{
string codeFriendlyName = TtsDebugger.OnDoString(this);
DynValue result = DoString(code, globalContext, codeFriendlyName);
TtsDebugger.OnStringDone(this);
return result;
try
{
string codeFriendlyName = TtsDebugger.OnDoString(this);
DynValue result = DoString(code, globalContext, codeFriendlyName);
return result;
}
finally
{
TtsDebugger.OnStringDone(this);
}
}

/// <summary>
Expand Down Expand Up @@ -569,7 +577,7 @@ public DynValue CreateCoroutine(object function)

/// <summary>
/// Gets or sets a value indicating whether the debugger is enabled.
/// Use this property if you want to disable the debugger for some
/// Use this property if you want to disable the debugger for some
/// executions.
/// </summary>
public bool DebuggerEnabled
Expand Down Expand Up @@ -732,17 +740,17 @@ public DynamicExpression CreateConstantDynamicExpression(string code, DynValue c
/// those cases where the execution engine is not really running - for example for dynamic expression
/// or calls from CLR to CLR callbacks
/// </summary>
internal ScriptExecutionContext CreateDynamicExecutionContext(CallbackFunction func = null)
public ScriptExecutionContext CreateDynamicExecutionContext(CallbackFunction func = null, int stackFrameIndex = -1)
{
return new ScriptExecutionContext(m_MainProcessor, func, null, isDynamic: true);
return new ScriptExecutionContext(m_MainProcessor, func, null, true, stackFrameIndex);
}

/// <summary>
/// MoonSharp (like Lua itself) provides a registry, a predefined table that can be used by any CLR code to
/// store whatever Lua values it needs to store.
/// Any CLR code can store data into this table, but it should take care to choose keys
/// that are different from those used by other libraries, to avoid collisions.
/// Typically, you should use as key a string GUID, a string containing your library name, or a
/// MoonSharp (like Lua itself) provides a registry, a predefined table that can be used by any CLR code to
/// store whatever Lua values it needs to store.
/// Any CLR code can store data into this table, but it should take care to choose keys
/// that are different from those used by other libraries, to avoid collisions.
/// Typically, you should use as key a string GUID, a string containing your library name, or a
/// userdata with the address of a CLR object in your code.
/// </summary>
public Table Registry
Expand Down
2 changes: 1 addition & 1 deletion src/MoonSharp.Interpreter/Tree/Expression_.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ internal static List<Expression> ExprList(ScriptLoadingContext lcontext)
lcontext.Lexer.Next();
}

return exps;
return exps;
}

internal static Expression Expr(ScriptLoadingContext lcontext)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace MoonSharp.Interpreter.Tree.Expressions
{
class AdjustmentExpression : Expression
class AdjustmentExpression : Expression
{
private Expression expression;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
namespace MoonSharp.Interpreter.Tree.Expressions
{
/// <summary>
///
///
/// </summary>
class BinaryOperatorExpression : Expression
{
[Flags]
private enum Operator
{
NotAnOperator = 0,
Or = 0x1,
NotAnOperator = 0,

Or = 0x1,
And = 0x2,
Less = 0x4,
Greater = 0x8,
Expand Down Expand Up @@ -140,7 +140,7 @@ private static Expression CreateSubTree(LinkedList list, ScriptLoadingContext lc
throw new InternalErrorException("Expression reduction didn't work! - 1");
if (nodes.Expr == null)
throw new InternalErrorException("Expression reduction didn't work! - 2");

return nodes.Expr;
}

Expand Down Expand Up @@ -353,7 +353,7 @@ public override DynValue Eval(ScriptExecutionContext context)

if ((m_Operator & COMPARES) != 0)
{
return DynValue.NewBoolean(EvalComparison(v1, v2, m_Operator));
return DynValue.NewBoolean(EvalComparison(v1, v2, m_Operator));
}
else if (m_Operator == Operator.StrConcat)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace MoonSharp.Interpreter.Tree.Expressions
{
class ExprListExpression : Expression
class ExprListExpression : Expression
{
List<Expression> expressions;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace MoonSharp.Interpreter.Tree.Expressions
{
class TableConstructor : Expression
class TableConstructor : Expression
{
bool m_Shared = false;
List<Expression> m_PositionalValues = new List<Expression>();
Expand Down
Loading

0 comments on commit a59a238

Please sign in to comment.