From a393699666b47781b1b38d348680ac9605e07ecd Mon Sep 17 00:00:00 2001 From: nub31 Date: Thu, 16 Oct 2025 16:25:02 +0200 Subject: [PATCH] Add basic defer implementation --- compiler/NubLang/Generation/Generator.cs | 36 ++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/compiler/NubLang/Generation/Generator.cs b/compiler/NubLang/Generation/Generator.cs index da995b9..3a501b2 100644 --- a/compiler/NubLang/Generation/Generator.cs +++ b/compiler/NubLang/Generation/Generator.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using NubLang.Ast; namespace NubLang.Generation; @@ -7,6 +8,8 @@ public class Generator private readonly List _definitions; private readonly HashSet _structTypes; private readonly IndentedTextWriter _writer; + private readonly Stack> _deferStack = []; + private int _tmpIndex; public Generator(List definitions, HashSet structTypes) { @@ -15,6 +18,12 @@ public class Generator _writer = new IndentedTextWriter(); } + // todo(nub31): Handle name collissions + private string NewTmp() + { + return $"_t{++_tmpIndex}"; + } + private static string MapType(NubType nubType) { return nubType switch @@ -246,7 +255,7 @@ public class Generator private void EmitDefer(DeferNode deferNode) { - throw new NotImplementedException(); + _deferStack.Peek().Add(deferNode); } private void EmitIf(IfNode ifNode) @@ -273,12 +282,27 @@ public class Generator { if (returnNode.Value == null) { + var blockDefers = _deferStack.Peek(); + for (var i = blockDefers.Count - 1; i >= 0; i--) + { + EmitStatement(blockDefers[i].Statement); + } + _writer.WriteLine("return;"); } else { 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("{"); using (_writer.Indent()) { + _deferStack.Push([]); + foreach (var statementNode in blockNode.Statements) { EmitStatement(statementNode); } + + var blockDefers = _deferStack.Pop(); + for (var i = blockDefers.Count - 1; i >= 0; i--) + { + EmitStatement(blockDefers[i].Statement); + } } _writer.WriteLine("}");