Skip to content

Commit

Permalink
handle then branch better
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjbreisch committed May 22, 2022
1 parent 8d435eb commit a40c9b3
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 34 deletions.
40 changes: 40 additions & 0 deletions Trs80.Level1Basic.Interpreter.Test/InterpreterTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -934,4 +934,44 @@ public void Interpreter_Evaluates_Logical_Expressions8()
controller.ReadOutputLine().Should().Be("FALSE");
controller.IsEndOfRun().Should().BeTrue();
}

[TestMethod]
public void Interpreter_Executes_Return_After_Then()
{
using var controller = new TestController();
var program = new List<string> {
"10 a=0",
"20 gosub 100",
"30 print \"SUCCESS!\"",
"40 end",
"100 if a = 0 then return",
"110 print \"FAIL!\"",
"120 end"
};

controller.RunProgram(program);

controller.ReadOutputLine().Should().Be("SUCCESS!");
controller.IsEndOfRun().Should().BeTrue();
}

[TestMethod]
public void Interpreter_Executes_Goto_After_Multiple_Thens()
{
using var controller = new TestController();
var program = new List<string> {
"10 a=0",
"20 if a = 0 then a = 1 : goto 100",
"30 print a",
"40 end",
"100 a = 2",
"110 print a",
"120 end"
};

controller.RunProgram(program);

controller.ReadOutputLine().Should().Be(" 2 ");
controller.IsEndOfRun().Should().BeTrue();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

using System;

namespace Trs80.Level1Basic.VirtualMachine.Exceptions;

public class ReturnFromGosub : Exception
{
}
56 changes: 23 additions & 33 deletions Trs80.Level1Basic.VirtualMachine/Interpreter/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Linq;
using System.Text;
using System.Threading;

using Microsoft.CSharp.RuntimeBinder;
using Trs80.Level1Basic.HostMachine;
using Trs80.Level1Basic.VirtualMachine.Exceptions;
using Trs80.Level1Basic.VirtualMachine.Machine;
Expand Down Expand Up @@ -233,6 +233,10 @@ public void Execute(IStatement statement)
{
statement.Accept(this);
}
catch (ReturnFromGosub)
{
throw;
}
catch (ScanException)
{
throw;
Expand Down Expand Up @@ -334,12 +338,10 @@ public Void VisitForStatement(For statement)

public Void VisitGosubStatement(Gosub statement)
{
IStatement nextStatement = _machine.GetNextStatement(_program.CurrentStatement);
IStatement resumeStatement = _machine.GetNextStatement(_program.CurrentStatement);

IStatement jumpToStatement = GetJumpToStatement(statement, statement.Location, "GOSUB");
_machine.RunStatementList(jumpToStatement, this, false);

_machine.SetNextStatement(nextStatement);
ExecuteGosub(jumpToStatement, resumeStatement);

return null!;
}
Expand All @@ -365,40 +367,19 @@ private IStatement GetStatementByLineNumber(int lineNumber)
public Void VisitGotoStatement(Goto statement)
{
IStatement jumpToStatement = GetJumpToStatement(statement, statement.Location, "GOTO");
_machine.RunStatementList(jumpToStatement, this, false);
_machine.ExecutionHalted = true;

_machine.SetNextStatement(jumpToStatement);
return null!;
}

public Void VisitIfStatement(If statement)
{
if (!IsTruthy(Evaluate(statement.Condition))) return null!;

IStatement thenStatement = statement.ThenBranch?[0];
if (thenStatement == null) return null!;
_machine.RunThenBranch(statement.ThenBranch, this);

switch (thenStatement)
{
case Goto gotoStatement:
VisitGotoStatement(gotoStatement);
break;
default:
ExecuteThenBranch(statement.ThenBranch);
break;
}
return null!;
}

private void ExecuteThenBranch(CompoundStatementList thenBranch)
{
IStatement nextStatement = _machine.GetNextStatement(_program.CurrentStatement);

_machine.RunStatementList(thenBranch[0], this, true);

_machine.SetNextStatement(nextStatement);
}

public Void VisitInputStatement(Input statement)
{
foreach (Expression expression in statement.Expressions)
Expand Down Expand Up @@ -594,8 +575,7 @@ public Void VisitOnStatement(On statement)
IStatement resumeStatement = _machine.GetNextStatement(statement);
Expression location = new Literal(locations[selector]);
IStatement jumpToStatement = GetJumpToStatement(statement, location, "GOSUB");
_machine.RunStatementList(jumpToStatement, this, false);
_machine.SetNextStatement(resumeStatement);
ExecuteGosub(jumpToStatement, resumeStatement);

return null!;
}
Expand All @@ -611,6 +591,18 @@ public Void VisitOnStatement(On statement)
return null!;
}

private void ExecuteGosub(IStatement jumpToStatement, IStatement resumeStatement)
{
try
{
_machine.RunStatementList(jumpToStatement, this, false);
}
catch (ReturnFromGosub)
{
_machine.SetNextStatement(resumeStatement);
}
}

public Void VisitPrintStatement(Print statement)
{
if (statement.AtPosition != null) PrintAt(statement.AtPosition);
Expand Down Expand Up @@ -674,9 +666,7 @@ public Void VisitRestoreStatement(Restore _)

public Void VisitReturnStatement(Return statement)
{
_machine.SetNextStatement(null);

return null!;
throw new ReturnFromGosub();
}

public Void VisitRunStatement(Run statement)
Expand Down
1 change: 1 addition & 0 deletions Trs80.Level1Basic.VirtualMachine/Machine/IMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface IMachine
void LoadProgram(string path);
void NewProgram();
void RunStatementList(IStatement statement, IInterpreter interpreter, bool breakOnLineChange);
void RunThenBranch(CompoundStatementList thenBranch, IInterpreter interpreter);
void SetNextStatement(IStatement statement);
void HaltRun();
IStatement GetStatementByLineNumber(int lineNumber);
Expand Down
19 changes: 19 additions & 0 deletions Trs80.Level1Basic.VirtualMachine/Machine/Machine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,25 @@ public void RunStatementList(IStatement statement, IInterpreter interpreter, boo
}
}

public void RunThenBranch(CompoundStatementList thenBranch, IInterpreter interpreter)
{
IStatement nextStatement = _nextStatement;

ExecutionHalted = false;
if (thenBranch == null) return;
int lineNumber = thenBranch.LineNumber;
IStatement statement = thenBranch[0];

while (statement != null && !ExecutionHalted)
{
_nextStatement = GetNextStatement(statement);
interpreter.Execute(statement);
if (statement is IListStatementDecorator decorated && decorated.BaseType() == typeof(Goto)) return;
statement = _nextStatement;
}
SetNextStatement(nextStatement);
}

public IStatement GetStatementByLineNumber(int lineNumber)
{
return Program.GetExecutableStatement(lineNumber);
Expand Down
1 change: 1 addition & 0 deletions Trs80.Level1Basic.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=builtins/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gosub/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hellogoodbye/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=hwnd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lucida/@EntryIndexedValue">True</s:Boolean>
Expand Down
2 changes: 1 addition & 1 deletion Trs80.Level1Basic/Samples/ParserTests/recursiveFib.bas
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
1030 gosub 1010
1040 n = n + 1
1050 a(n) = a(n-1) + a(n-2)
1060 rem runprint "#1060 n=";n;"a(";n;")=";a(n);"a(";n-1;")=";a(n-1);"a(";n-2;")=";a(n-2)
1060 rem print "#1060 n=";n;"a(";n;")=";a(n);"a(";n-1;")=";a(n-1);"a(";n-2;")=";a(n-2)
1070 return

0 comments on commit a40c9b3

Please sign in to comment.