Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 25 additions & 30 deletions src/Neo.VM/Collections/OrderedDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,37 @@ namespace Neo.VM.Collections
internal class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
where TKey : notnull
{
private class TItem
private class TItem(TKey key, TValue value)
{
public readonly TKey Key;
public TValue Value;

public TItem(TKey key, TValue value)
{
Key = key;
Value = value;
}
public readonly TKey Key = key;
public TValue Value = value;
}

private class InternalCollection : KeyedCollection<TKey, TItem>
{
protected override TKey GetKeyForItem(TItem item)
{
return item.Key;
}
protected override TKey GetKeyForItem(TItem item) => item.Key;
}

private readonly InternalCollection collection = new();
private readonly InternalCollection _collection = new();

public int Count => _collection.Count;

public int Count => collection.Count;
public bool IsReadOnly => false;
public ICollection<TKey> Keys => collection.Select(p => p.Key).ToArray();
public ICollection<TValue> Values => collection.Select(p => p.Value).ToArray();

public ICollection<TKey> Keys => _collection.Select(p => p.Key).ToArray();

public ICollection<TValue> Values => _collection.Select(p => p.Value).ToArray();


public TValue this[TKey key]
{
get
{
return collection[key].Value;
return _collection[key].Value;
}
set
{
if (collection.TryGetValue(key, out var entry))
if (_collection.TryGetValue(key, out var entry))
entry.Value = value;
else
Add(key, value);
Expand All @@ -64,25 +59,25 @@ public TValue this[TKey key]

public void Add(TKey key, TValue value)
{
collection.Add(new TItem(key, value));
_collection.Add(new TItem(key, value));
}

public bool ContainsKey(TKey key)
{
return collection.Contains(key);
return _collection.Contains(key);
}

public bool Remove(TKey key)
{
return collection.Remove(key);
return _collection.Remove(key);
}

// supress warning of value parameter nullability mismatch
#pragma warning disable CS8767
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value)
#pragma warning restore CS8767
{
if (collection.TryGetValue(key, out var entry))
if (_collection.TryGetValue(key, out var entry))
{
value = entry.Value;
return true;
Expand All @@ -98,33 +93,33 @@ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item

public void Clear()
{
collection.Clear();
_collection.Clear();
}

bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
{
return collection.Contains(item.Key);
return _collection.Contains(item.Key);
}

void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
for (int i = 0; i < collection.Count; i++)
array[i + arrayIndex] = new KeyValuePair<TKey, TValue>(collection[i].Key, collection[i].Value);
for (int i = 0; i < _collection.Count; i++)
array[i + arrayIndex] = new KeyValuePair<TKey, TValue>(_collection[i].Key, _collection[i].Value);
}

bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
{
return collection.Remove(item.Key);
return _collection.Remove(item.Key);
}

IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
{
return collection.Select(p => new KeyValuePair<TKey, TValue>(p.Key, p.Value)).GetEnumerator();
return _collection.Select(p => new KeyValuePair<TKey, TValue>(p.Key, p.Value)).GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return collection.Select(p => new KeyValuePair<TKey, TValue>(p.Key, p.Value)).GetEnumerator();
return _collection.Select(p => new KeyValuePair<TKey, TValue>(p.Key, p.Value)).GetEnumerator();
}
}
}
85 changes: 46 additions & 39 deletions src/Neo.VM/Debugger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,30 @@ namespace Neo.VM
/// </summary>
public class Debugger
{
private readonly ExecutionEngine engine;
private readonly Dictionary<Script, HashSet<uint>> break_points = new();
private readonly ExecutionEngine _engine;
private readonly Dictionary<Script, HashSet<uint>> _breakPoints = new();

/// <summary>
/// Create a debugger on the specified <see cref="ExecutionEngine"/>.
/// </summary>
/// <param name="engine">The <see cref="ExecutionEngine"/> to attach the debugger.</param>
public Debugger(ExecutionEngine engine)
{
this.engine = engine;
_engine = engine;
}

/// <summary>
/// Add a breakpoint at the specified position of the specified script. The VM will break the execution when it reaches the breakpoint.
/// Add a breakpoint at the specified position of the specified script.
/// The VM will break the execution when it reaches the breakpoint.
/// </summary>
/// <param name="script">The script to add the breakpoint.</param>
/// <param name="position">The position of the breakpoint in the script.</param>
public void AddBreakPoint(Script script, uint position)
{
if (!break_points.TryGetValue(script, out HashSet<uint>? hashset))
if (!_breakPoints.TryGetValue(script, out var hashset))
{
hashset = new HashSet<uint>();
break_points.Add(script, hashset);
_breakPoints.Add(script, hashset);
}
hashset.Add(position);
}
Expand All @@ -51,20 +52,23 @@ public void AddBreakPoint(Script script, uint position)
/// <returns>Returns the state of the VM after the execution.</returns>
public VMState Execute()
{
if (engine.State == VMState.BREAK)
engine.State = VMState.NONE;
while (engine.State == VMState.NONE)
if (_engine.State == VMState.BREAK)
_engine.State = VMState.NONE;
while (_engine.State == VMState.NONE)
ExecuteAndCheckBreakPoints();
return engine.State;
return _engine.State;
}

private void ExecuteAndCheckBreakPoints()
{
engine.ExecuteNext();
if (engine.State == VMState.NONE && engine.InvocationStack.Count > 0 && break_points.Count > 0)
_engine.ExecuteNext();
if (_engine.State == VMState.NONE && _engine.InvocationStack.Count > 0 && _breakPoints.Count > 0)
{
if (break_points.TryGetValue(engine.CurrentContext!.Script, out var hashset) && hashset.Contains((uint)engine.CurrentContext.InstructionPointer))
engine.State = VMState.BREAK;
if (_breakPoints.TryGetValue(_engine.CurrentContext!.Script, out var hashset) &&
hashset.Contains((uint)_engine.CurrentContext.InstructionPointer))
{
_engine.State = VMState.BREAK;
}
}
}

Expand All @@ -79,24 +83,26 @@ private void ExecuteAndCheckBreakPoints()
/// </returns>
public bool RemoveBreakPoint(Script script, uint position)
{
if (!break_points.TryGetValue(script, out var hashset)) return false;
if (!_breakPoints.TryGetValue(script, out var hashset)) return false;
if (!hashset.Remove(position)) return false;
if (hashset.Count == 0) break_points.Remove(script);
if (hashset.Count == 0) _breakPoints.Remove(script);
return true;
}

/// <summary>
/// Execute the next instruction. If the instruction involves a call to a method, it steps into the method and breaks the execution on the first instruction of that method.
/// Execute the next instruction.
/// If the instruction involves a call to a method,
/// it steps into the method and breaks the execution on the first instruction of that method.
/// </summary>
/// <returns>The VM state after the instruction is executed.</returns>
public VMState StepInto()
{
if (engine.State == VMState.HALT || engine.State == VMState.FAULT)
return engine.State;
engine.ExecuteNext();
if (engine.State == VMState.NONE)
engine.State = VMState.BREAK;
return engine.State;
if (_engine.State == VMState.HALT || _engine.State == VMState.FAULT)
return _engine.State;
_engine.ExecuteNext();
if (_engine.State == VMState.NONE)
_engine.State = VMState.BREAK;
return _engine.State;
}

/// <summary>
Expand All @@ -105,34 +111,35 @@ public VMState StepInto()
/// <returns>The VM state after the currently executed method is returned.</returns>
public VMState StepOut()
{
if (engine.State == VMState.BREAK)
engine.State = VMState.NONE;
int c = engine.InvocationStack.Count;
while (engine.State == VMState.NONE && engine.InvocationStack.Count >= c)
if (_engine.State == VMState.BREAK)
_engine.State = VMState.NONE;
int c = _engine.InvocationStack.Count;
while (_engine.State == VMState.NONE && _engine.InvocationStack.Count >= c)
ExecuteAndCheckBreakPoints();
if (engine.State == VMState.NONE)
engine.State = VMState.BREAK;
return engine.State;
if (_engine.State == VMState.NONE)
_engine.State = VMState.BREAK;
return _engine.State;
}

/// <summary>
/// Execute the next instruction. If the instruction involves a call to a method, it does not step into the method (it steps over it instead).
/// Execute the next instruction.
/// If the instruction involves a call to a method, it does not step into the method (it steps over it instead).
/// </summary>
/// <returns>The VM state after the instruction is executed.</returns>
public VMState StepOver()
{
if (engine.State == VMState.HALT || engine.State == VMState.FAULT)
return engine.State;
engine.State = VMState.NONE;
int c = engine.InvocationStack.Count;
if (_engine.State == VMState.HALT || _engine.State == VMState.FAULT)
return _engine.State;
_engine.State = VMState.NONE;
int c = _engine.InvocationStack.Count;
do
{
ExecuteAndCheckBreakPoints();
}
while (engine.State == VMState.NONE && engine.InvocationStack.Count > c);
if (engine.State == VMState.NONE)
engine.State = VMState.BREAK;
return engine.State;
while (_engine.State == VMState.NONE && _engine.InvocationStack.Count > c);
if (_engine.State == VMState.NONE)
_engine.State = VMState.BREAK;
return _engine.State;
}
}
}
Loading