Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch VariableScope to link directly to its parent #2141

Merged
merged 1 commit into from
Oct 27, 2017
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
5 changes: 5 additions & 0 deletions src/kOS.Safe.Test/Opcode/FakeCpu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ public object PopScopeStack(int howMany)
throw new NotImplementedException();
}

public void PushNewScope(Int16 scopeId, Int16 parentScopeId)
{
throw new NotImplementedException();
}

public List<VariableScope> GetCurrentClosure()
{
throw new NotImplementedException();
Expand Down
2 changes: 1 addition & 1 deletion src/kOS.Safe/Compilation/Opcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1964,7 +1964,7 @@ public override void PopulateFromMLFields(List<object> fields)

public override void Execute(ICpu cpu)
{
cpu.PushScopeStack(new VariableScope(ScopeId,ParentScopeId));
cpu.PushNewScope(ScopeId,ParentScopeId);
}

public override string ToString()
Expand Down
226 changes: 72 additions & 154 deletions src/kOS.Safe/Execution/CPU.cs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/kOS.Safe/Execution/ICpu.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using kOS.Safe.Compilation;
using kOS.Safe.Encapsulation;
Expand All @@ -8,6 +9,7 @@ public interface ICpu : IFixedUpdateObserver
{
void PushArgumentStack(object item);
object PopArgumentStack();
void PushNewScope(Int16 scopeId, Int16 parentScopeId);
void PushScopeStack(object thing);
object PopScopeStack(int howMany);
List<VariableScope> GetCurrentClosure();
Expand Down
5 changes: 4 additions & 1 deletion src/kOS.Safe/Execution/IStack.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;

namespace kOS.Safe.Execution
{
Expand All @@ -17,5 +18,7 @@ public interface IStack
string Dump();
List<int> GetCallTrace();
bool HasTriggerContexts();
VariableScope FindScope(Int16 scopeId);
VariableScope GetCurrentScope();
}
}
41 changes: 36 additions & 5 deletions src/kOS.Safe/Execution/Stack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -333,19 +333,50 @@ private void dumpItem(int index, bool isSP, object item, StringBuilder builder)
VariableScope dict = item as VariableScope;
if (dict != null)
{
builder.AppendFormat(" ScopeId={0}, ParentScopeId={1}, ParentSkipLevels={2} IsClosure={3}",
dict.ScopeId, dict.ParentScopeId, dict.ParentSkipLevels, dict.IsClosure);
Int16 parentScopeId = -1;
if (dict.ParentScope != null)
{
parentScopeId = dict.ParentScope.ScopeId;
}

builder.AppendFormat(" ScopeId={0}, ParentScopeId={1}, IsClosure={2}",
dict.ScopeId, parentScopeId, dict.IsClosure);
builder.AppendLine();
// Dump the local variable context stored here on the stack:
foreach (string varName in dict.Variables.Keys)
foreach (var entry in dict.Locals)
{
var value = dict.Variables[varName].Value;
builder.AppendFormat(" local var {0} is {1} with value = {2}", varName, KOSNomenclature.GetKOSName(value.GetType()), dict.Variables[varName].Value);
builder.AppendFormat(" local var {0} is {1} with value = {2}", entry.Key, KOSNomenclature.GetKOSName(entry.Value.GetType()), entry.Value);
builder.AppendLine();
}
}
}

public VariableScope FindScope(Int16 ScopeId)
{
for (int index = scopeCount - 1; index >= 0; --index)
{
var scope = scopeStack[index] as VariableScope;
if (scope != null && scope.ScopeId == ScopeId)
{
return scope;
}
}
return null;
}

public VariableScope GetCurrentScope()
{
for (int index = scopeCount - 1; index >= 0; --index)
{
var scope = scopeStack[index] as VariableScope;
if (scope != null)
{
return scope;
}
}
return null;
}

/// <summary>
/// Return the subroutine call trace of how the code got to where it is right now.
/// </summary>
Expand Down
81 changes: 65 additions & 16 deletions src/kOS.Safe/Execution/VariableScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,8 @@ public class VariableScope
/// An ID of 0 means global.
/// </summary>
public Int16 ScopeId {get;set;}

/// <summary>
/// The unique ID of this variable scope's parent scope.
/// An ID of 0 means global.
/// </summary>
public Int16 ParentScopeId {get;set;}

/// <summary>
/// Once the ParentId has been used once to detect which VaraibleScope
/// is the parent of this scope, you can store the result here so you
/// can jump there quicker next time without scanning the scope stack.
/// </summary>
public Int16 ParentSkipLevels {get;set;}
public VariableScope ParentScope {get;set;}

/// <summary>
/// Set this to true to indicate that this scope is part of a closure
Expand All @@ -38,15 +27,75 @@ public class VariableScope
/// </summary>
public bool IsClosure {get;set;}

public Dictionary<string, Variable> Variables;
private Dictionary<string, Variable> Variables;

public VariableScope(Int16 scopeId, Int16 parentScopeId)
public VariableScope(Int16 scopeId, VariableScope parentScope)
{
ScopeId = scopeId;
ParentScopeId = parentScopeId;
ParentSkipLevels = 1; // the default case is to just move one stack level.
ParentScope = parentScope;
Variables = new Dictionary<string, Variable>(StringComparer.OrdinalIgnoreCase);
IsClosure = false;
}

public IEnumerable<KeyValuePair<string, Variable>> Locals
{
get
{
return Variables;
}
}

public void Clear()
{
Variables.Clear();
}

public void Add(string name, Variable value)
{
Variables[name] = value;
}

public bool Remove(string name)
{
return Variables.Remove(name);
}

public Variable RemoveNested(string name)
{
Variable res = null;

if (!Variables.TryGetValue(name, out res))
{
return ParentScope.RemoveNested(name);
}
Variables.Remove(name);

return res;
}

public bool Contains(string name)
{
return Variables.ContainsKey(name);
}

public Variable GetNested(string name)
{
Variable res;
if (!Variables.TryGetValue(name, out res) && ParentScope != null)
{
res = ParentScope.GetNested(name);
}
return res;
}

public Variable GetLocal(string name)
{
Variable res = null;

// Just return null if this doesn't fill it
Variables.TryGetValue(name, out res);

return res;
}
}
}