Skip to content

Commit

Permalink
Fix break and continue
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardoboss committed Dec 23, 2023
1 parent 720077d commit 99c2e5e
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 72 deletions.
36 changes: 28 additions & 8 deletions StepLang.Tests/Examples/looping.step.out
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,35 @@ c: 3
4
5
5
break out of a loop
continue to the next iteration
1
2
4
5
1
2
1
2
1
2
1
2
nested continue
inner: 1
inner: 2
outer: 1
inner: 1
inner: 2
outer: 2
inner: 1
inner: 2
outer (skipped): 3
inner: 1
inner: 2
outer (skipped): 4
inner: 1
inner: 2
outer (skipped): 5
nested break
inner: 1
inner: 2
outer: 1
inner: 1
inner: 2
outer: 2
inner: 1
inner: 2
outer (skipped): 3
20 changes: 12 additions & 8 deletions StepLang/Examples/looping.step
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ foreach (number x in nums) {
println(x)
}

// break out of a loop
println("break out of a loop")
while (true) {
break

println("should not get printed")
}

// continue to the next iteration
println("continue to the next iteration")
foreach (number n in [1, 2, 3, 4, 5]) {
if (n == 3) {
continue
Expand All @@ -89,7 +89,7 @@ foreach (number n in [1, 2, 3, 4, 5]) {
println(n)
}

// nested continue
println("nested continue")
foreach (number n in [1, 2, 3, 4, 5]) {
foreach (number n2 in [1, 2, 3, 4, 5]) {
if (n2 >= 3) {
Expand All @@ -98,19 +98,21 @@ foreach (number n in [1, 2, 3, 4, 5]) {
println("should not get printed")
}

println(n2)
println("inner: ", n2)
}

if (n >= 3) {
println("outer (skipped): ", n)

continue

println("should not get printed")
}

println(n)
println("outer: ", n)
}

// nested break
println("nested break")
foreach (number n in [1, 2, 3, 4, 5]) {
foreach (number n2 in [1, 2, 3, 4, 5]) {
if (n2 == 3) {
Expand All @@ -119,14 +121,16 @@ foreach (number n in [1, 2, 3, 4, 5]) {
println("should not get printed")
}

println(n2)
println("inner: ", n2)
}

if (n == 3) {
println("outer (skipped): ", n)

break

println("should not get printed")
}

println(n)
println("outer: ", n)
}
10 changes: 10 additions & 0 deletions StepLang/Interpreting/Interpreter.Branching.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,14 @@ public void Execute(IfElseIfStatementNode statementNode)
if (elseResult.IsTruthy())
Execute(statementNode.ElseBody);
}

public void Execute(ContinueStatementNode statementNode)
{
CurrentScope.SetContinue();
}

public void Execute(BreakStatementNode statementNode)
{
CurrentScope.SetBreak();
}
}
11 changes: 0 additions & 11 deletions StepLang/Interpreting/Interpreter.Break.cs

This file was deleted.

11 changes: 0 additions & 11 deletions StepLang/Interpreting/Interpreter.Continue.cs

This file was deleted.

29 changes: 17 additions & 12 deletions StepLang/Interpreting/Interpreter.Foreach.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,30 +140,35 @@ private void RunForeachLoop(Action<ExpressionResult>? updateKey, Action<Expressi

foreach (var (keyValue, valueValue) in pairs)
{
PushScope();
var loopScope = PushScope();

// update/initialize key and value in loop scope
updateKey?.Invoke(keyValue);
updateValue(valueValue);

Execute(body);

if (BreakDepth > 0)
foreach (var statement in body)
{
BreakDepth--;

PopScope();
Execute(statement);

break;
if (loopScope.ShouldReturn() || loopScope.ShouldBreak() || loopScope.ShouldContinue())
break;
}

if (CurrentScope.TryGetResult(out var resultValue, out var resultLocation))
{
PopScope();
_ = PopScope();

// handle returns to parent scope
if (loopScope.TryGetResult(out var resultValue, out var resultLocation))
{
CurrentScope.SetResult(resultLocation, resultValue);

break;
return;
}

// break out of loop
if (loopScope.ShouldBreak())
return;

// continue is implicitly handled
}
}
}
22 changes: 14 additions & 8 deletions StepLang/Interpreting/Interpreter.While.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,31 @@ public void Execute(WhileStatementNode statementNode)
{
while (ShouldLoop())
{
PushScope();
var loopScope = PushScope();

Execute(statementNode.Body);

var loopScope = PopScope();

if (BreakDepth > 0)
foreach (var statement in statementNode.Body)
{
BreakDepth--;
Execute(statement);

break;
if (loopScope.ShouldReturn() || loopScope.ShouldBreak() || loopScope.ShouldContinue())
break;
}

_ = PopScope();

// handle returns to parent scope
if (loopScope.TryGetResult(out var resultValue, out var resultLocation))
{
CurrentScope.SetResult(resultLocation, resultValue);

return;
}

// break out of loop
if (loopScope.ShouldBreak())
return;

// continue is implicitly handled
}

return;
Expand Down
29 changes: 15 additions & 14 deletions StepLang/Interpreting/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ public partial class Interpreter : IRootNodeVisitor, IStatementVisitor, IExpress
public TextWriter? DebugOut { get; }
public int ExitCode { get; set; }

public int BreakDepth { get; set; }

public int ContinueDepth { get; set; }

private readonly Stack<Scope> scopes = new();

private Lazy<Random> random = new(() => new());
Expand Down Expand Up @@ -58,23 +54,28 @@ public void Execute(IEnumerable<StatementNode> statements)
{
foreach (var statement in statements)
{
if (ContinueDepth > 0)
{
ContinueDepth--;
Execute(statement);

DebugOut?.WriteLine("Continuing");
if (CurrentScope.TryGetResult(out _, out _))
{
DebugOut?.WriteLine("Result found, continuing");

break;
return;
}

Execute(statement);
if (CurrentScope.ShouldBreak())
{
DebugOut?.WriteLine("Break found, breaking");

if (!CurrentScope.TryGetResult(out _, out _))
continue;
return;
}

DebugOut?.WriteLine("Result found, continuing");
if (CurrentScope.ShouldContinue())
{
DebugOut?.WriteLine("Continue found, continuing");

break;
return;
}
}
}

Expand Down
13 changes: 13 additions & 0 deletions StepLang/Interpreting/Scope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ public class Scope
private TokenLocation? scopeResultLocation;
private ExpressionResult? scopeResult;

private bool shouldContinue;
private bool shouldBreak;

public Scope(Scope parent) => parentScope = parent;

private Scope()
Expand Down Expand Up @@ -150,6 +153,8 @@ public void SetResult(TokenLocation location, ExpressionResult result)
scopeResult = result;
}

public bool ShouldReturn() => scopeResult is not null;

public bool TryGetResult([NotNullWhen(true)] out ExpressionResult? result, [NotNullWhen(true)] out TokenLocation? location)
{
location = scopeResultLocation;
Expand All @@ -158,6 +163,14 @@ public bool TryGetResult([NotNullWhen(true)] out ExpressionResult? result, [NotN
return result is not null;
}

public void SetContinue() => shouldContinue = true;

public void SetBreak() => shouldBreak = true;

public bool ShouldContinue() => shouldContinue;

public bool ShouldBreak() => shouldBreak;

public override string ToString()
{
return $"Scope: {{{string.Join(", ", identifiers.Select(kvp => kvp.Value.ToString()))}}}";
Expand Down

0 comments on commit 99c2e5e

Please sign in to comment.