This commit is contained in:
nub31
2025-09-20 19:59:48 +02:00
parent f6c686a635
commit 511f0d27ee
3 changed files with 25 additions and 63 deletions

View File

@@ -498,6 +498,9 @@ public class QBEGenerator
EmitScopeCleanup(); EmitScopeCleanup();
_writer.Indented($"jmp {_continueLabels.Peek()}"); _writer.Indented($"jmp {_continueLabels.Peek()}");
break; break;
case DeferNode defer:
Scope.Defers.Push(defer);
break;
case IfNode ifStatement: case IfNode ifStatement:
EmitIf(ifStatement); EmitIf(ifStatement);
break; break;
@@ -523,6 +526,11 @@ public class QBEGenerator
private void EmitScopeCleanup() private void EmitScopeCleanup()
{ {
while (Scope.Defers.TryPop(out var defer))
{
EmitStatement(defer.Statement);
}
while (Scope.Variables.TryPop(out var variable)) while (Scope.Variables.TryPop(out var variable))
{ {
if (variable.Type is NubStructType structType) if (variable.Type is NubStructType structType)
@@ -1283,6 +1291,7 @@ public class QBEGenerator
public class Scope public class Scope
{ {
public readonly Stack<Variable> Variables = []; public readonly Stack<Variable> Variables = [];
public readonly Stack<DeferNode> Defers = [];
} }
public record Variable(string Name, NubType Type); public record Variable(string Name, NubType Type);

View File

@@ -23,3 +23,5 @@ public record ContinueNode : TerminalStatementNode;
public record BreakNode : TerminalStatementNode; public record BreakNode : TerminalStatementNode;
public record WhileNode(ExpressionNode Condition, BlockNode Body) : StatementNode; public record WhileNode(ExpressionNode Condition, BlockNode Body) : StatementNode;
public record DeferNode(StatementNode Statement) : StatementNode;

View File

@@ -1,5 +1,4 @@
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using NubLang.Diagnostics; using NubLang.Diagnostics;
using NubLang.Modules; using NubLang.Modules;
@@ -764,12 +763,6 @@ public sealed class TypeChecker
BeginScope(false); BeginScope(false);
foreach (var statement in node.Statements) foreach (var statement in node.Statements)
{
if (statement is DeferSyntax deferStmt)
{
CurrentScope.PushDefer(deferStmt);
}
else
{ {
var checkedStatement = CheckStatement(statement); var checkedStatement = CheckStatement(statement);
@@ -777,21 +770,6 @@ public sealed class TypeChecker
{ {
if (checkedStatement is TerminalStatementNode) if (checkedStatement is TerminalStatementNode)
{ {
while (CurrentScope.TryPopDefer(out var defer))
{
var checkedDeferredStatement = CheckStatement(defer.Statement);
if (checkedDeferredStatement is TerminalStatementNode)
{
throw new TypeCheckerException(Diagnostic
.Error("Cannot defer terminal statements")
.WithHelp("Avoid using defer with terminal statements such as 'return', 'break', 'continue' etc.")
.At(defer)
.Build());
}
statements.Add(checkedDeferredStatement);
}
reachable = false; reachable = false;
} }
@@ -806,22 +784,6 @@ public sealed class TypeChecker
} }
} }
} }
}
while (CurrentScope.TryPopDefer(out var defer))
{
var checkedDeferredStatement = CheckStatement(defer.Statement);
if (checkedDeferredStatement is TerminalStatementNode)
{
throw new TypeCheckerException(Diagnostic
.Error("Cannot defer terminal statements")
.WithHelp("Avoid using defer with terminal statements such as 'return', 'break', 'continue' etc.")
.At(defer)
.Build());
}
statements.Add(checkedDeferredStatement);
}
EndScope(); EndScope();
@@ -841,7 +803,7 @@ public sealed class TypeChecker
StatementExpressionSyntax stmtExpr => CheckStatementExpression(stmtExpr), StatementExpressionSyntax stmtExpr => CheckStatementExpression(stmtExpr),
VariableDeclarationSyntax varDeclStmt => CheckVariableDeclaration(varDeclStmt), VariableDeclarationSyntax varDeclStmt => CheckVariableDeclaration(varDeclStmt),
WhileSyntax whileStmt => CheckWhile(whileStmt), WhileSyntax whileStmt => CheckWhile(whileStmt),
DeferSyntax => throw new InvalidOperationException($"Compiler bug: defer statement should not have reached {nameof(CheckStatement)}"), DeferSyntax defer => new DeferNode(CheckStatement(defer.Statement)),
_ => throw new ArgumentOutOfRangeException(nameof(statement)) _ => throw new ArgumentOutOfRangeException(nameof(statement))
}; };
} }
@@ -957,7 +919,6 @@ public record Variable(string Name, NubType Type, VariableKind Kind);
public class Scope(Scope? parent = null) public class Scope(Scope? parent = null)
{ {
private readonly Stack<DeferSyntax> _defers = [];
private readonly List<Variable> _variables = []; private readonly List<Variable> _variables = [];
public Variable? LookupVariable(string name) public Variable? LookupVariable(string name)
@@ -976,16 +937,6 @@ public class Scope(Scope? parent = null)
_variables.Add(variable); _variables.Add(variable);
} }
public void PushDefer(DeferSyntax defer)
{
_defers.Push(defer);
}
public bool TryPopDefer([NotNullWhen(true)] out DeferSyntax? defer)
{
return _defers.TryPop(out defer);
}
public Scope SubScope() public Scope SubScope()
{ {
return new Scope(this); return new Scope(this);