Add basic defer implementation

This commit is contained in:
nub31
2025-10-16 16:25:02 +02:00
parent a7d5479dab
commit a393699666

View File

@@ -1,3 +1,4 @@
using System.Diagnostics;
using NubLang.Ast; using NubLang.Ast;
namespace NubLang.Generation; namespace NubLang.Generation;
@@ -7,6 +8,8 @@ public class Generator
private readonly List<DefinitionNode> _definitions; private readonly List<DefinitionNode> _definitions;
private readonly HashSet<NubStructType> _structTypes; private readonly HashSet<NubStructType> _structTypes;
private readonly IndentedTextWriter _writer; private readonly IndentedTextWriter _writer;
private readonly Stack<List<DeferNode>> _deferStack = [];
private int _tmpIndex;
public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes) public Generator(List<DefinitionNode> definitions, HashSet<NubStructType> structTypes)
{ {
@@ -15,6 +18,12 @@ public class Generator
_writer = new IndentedTextWriter(); _writer = new IndentedTextWriter();
} }
// todo(nub31): Handle name collissions
private string NewTmp()
{
return $"_t{++_tmpIndex}";
}
private static string MapType(NubType nubType) private static string MapType(NubType nubType)
{ {
return nubType switch return nubType switch
@@ -246,7 +255,7 @@ public class Generator
private void EmitDefer(DeferNode deferNode) private void EmitDefer(DeferNode deferNode)
{ {
throw new NotImplementedException(); _deferStack.Peek().Add(deferNode);
} }
private void EmitIf(IfNode ifNode) private void EmitIf(IfNode ifNode)
@@ -273,12 +282,27 @@ public class Generator
{ {
if (returnNode.Value == null) if (returnNode.Value == null)
{ {
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
_writer.WriteLine("return;"); _writer.WriteLine("return;");
} }
else else
{ {
var returnValue = EmitExpression(returnNode.Value); var returnValue = EmitExpression(returnNode.Value);
_writer.WriteLine($"return {returnValue};"); var tmp = NewTmp();
_writer.WriteLine($"{MapType(returnNode.Value.Type)} {tmp} = {returnValue};");
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
_writer.WriteLine($"return {tmp};");
} }
} }
@@ -559,10 +583,18 @@ public class Generator
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
_deferStack.Push([]);
foreach (var statementNode in blockNode.Statements) foreach (var statementNode in blockNode.Statements)
{ {
EmitStatement(statementNode); EmitStatement(statementNode);
} }
var blockDefers = _deferStack.Pop();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitStatement(blockDefers[i].Statement);
}
} }
_writer.WriteLine("}"); _writer.WriteLine("}");