Skip to content

Commit

Permalink
Fix for ResetCallstack() not resetting base callstack element.
Browse files Browse the repository at this point in the history
  • Loading branch information
joethephish committed Nov 21, 2018
1 parent 347eaaa commit d7af969
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 12 deletions.
23 changes: 17 additions & 6 deletions ink-engine-runtime/CallStack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,22 +176,31 @@ public bool canPop {
}
}

public CallStack (Container rootContentContainer)
public CallStack (Story storyContext)
{
_threads = new List<Thread> ();
_threads.Add (new Thread ());

_threads [0].callstack.Add (new Element (PushPopType.Tunnel, Pointer.StartOf(rootContentContainer)));
_startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);
Reset();
}


public CallStack(CallStack toCopy)
{
_threads = new List<Thread> ();
foreach (var otherThread in toCopy._threads) {
_threads.Add (otherThread.Copy ());
}
_startOfRoot = toCopy._startOfRoot;
}


public void Reset()
{
_threads = new List<Thread>();
_threads.Add(new Thread());

_threads[0].callstack.Add(new Element(PushPopType.Tunnel, _startOfRoot));
}


// Unfortunately it's not possible to implement jsonToken since
// the setter needs to take a Story as a context in order to
// look up objects from paths for currentContainer within elements.
Expand All @@ -208,6 +217,7 @@ public void SetJsonToken(Dictionary<string, object> jObject, Story storyContext)
}

_threadCounter = (int)jObject ["threadCounter"];
_startOfRoot = Pointer.StartOf(storyContext.rootContentContainer);
}

// See above for why we can't implement jsonToken
Expand Down Expand Up @@ -399,6 +409,7 @@ internal string callStackTrace {

List<Thread> _threads;
int _threadCounter;
Pointer _startOfRoot;
}
}

8 changes: 2 additions & 6 deletions ink-engine-runtime/StoryState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ internal StoryState (Story story)

evaluationStack = new List<Runtime.Object> ();

callStack = new CallStack (story.rootContentContainer);
callStack = new CallStack (story);
variablesState = new VariablesState (callStack, story.listDefinitions);

visitCounts = new Dictionary<string, int> ();
Expand Down Expand Up @@ -809,11 +809,7 @@ internal Runtime.Object PeekEvaluationStack()
/// </summary>
public void ForceEnd()
{
while (callStack.canPopThread)
callStack.PopThread ();

while (callStack.canPop)
PopCallstack ();
callStack.Reset();

_currentChoices.Clear();

Expand Down
31 changes: 31 additions & 0 deletions tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3658,6 +3658,37 @@ public void TestFallbackChoiceOnThread()
Assert.AreEqual("Should be 1 not 0: 1.\n", story.Continue());
}

// Test for bug where after a call to ChoosePathString,
// the callstack is not fully/cleanly reset, e.g. leaving
// "inExpressionEvaluation" variable left to true, as set during
// the call to {RunAThing()}.
// This was when we unwound the callstack, but we didn't reset
// the base element.
[Test()]
public void TestCleanCallstackResetOnPathChoice()
{
var storyStr =
@"
{RunAThing()}
== function RunAThing ==
The first line.
The second line.
== SomewhereElse ==
{""somewhere else""}
->END
";

var story = CompileString(storyStr);

Assert.AreEqual("The first line.\n", story.Continue());

story.ChoosePathString("SomewhereElse");

Assert.AreEqual("somewhere else\n", story.ContinueMaximally());
}

// Helper compile function
protected Story CompileString(string str, bool countAllVisits = false, bool testingErrors = false)
{
Expand Down

0 comments on commit d7af969

Please sign in to comment.