From d11df414ad23d6b56477bf5ddbf2faf2f43f4069 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sun, 26 Oct 2025 17:05:56 +0100 Subject: [PATCH] Refs working? --- compiler/NubLang/Generation/Generator.cs | 158 +++++++++++++++-------- examples/playgroud/main.nub | 7 + runtime/ref.c | 4 +- 3 files changed, 113 insertions(+), 56 deletions(-) diff --git a/compiler/NubLang/Generation/Generator.cs b/compiler/NubLang/Generation/Generator.cs index fc16f28..d773102 100644 --- a/compiler/NubLang/Generation/Generator.cs +++ b/compiler/NubLang/Generation/Generator.cs @@ -9,10 +9,11 @@ public class Generator { private readonly CompilationUnit _compilationUnit; private readonly IndentedTextWriter _writer; - private readonly Stack> _deferStack = []; - private readonly Stack> _refCleanupStack = []; + private readonly Stack _scopes = []; private int _tmpIndex; + private Scope Scope => _scopes.Peek(); + public Generator(CompilationUnit compilationUnit) { _compilationUnit = compilationUnit; @@ -103,7 +104,18 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - EmitBlock(funcNode.Body); + using (BeginScope()) + { + foreach (var parameter in funcNode.Prototype.Parameters) + { + if (parameter.Type is NubRefType) + { + Scope.Defer(() => _writer.WriteLine($"rc_release({parameter.NameToken.Value});")); + } + } + + EmitBlock(funcNode.Body); + } } _writer.WriteLine("}"); @@ -125,7 +137,10 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - EmitBlock(blockNode); + using (BeginScope()) + { + EmitBlock(blockNode); + } } _writer.WriteLine("}"); @@ -137,7 +152,7 @@ public class Generator EmitContinue(continueNode); break; case DeferNode deferNode: - EmitDefer(deferNode); + Scope.Defer(() => EmitStatement(deferNode.Statement)); break; case ForConstArrayNode forConstArrayNode: EmitForConstArray(forConstArrayNode); @@ -177,6 +192,13 @@ public class Generator { var target = EmitExpression(assignmentNode.Target); var value = EmitExpression(assignmentNode.Value); + + if (assignmentNode.Target.Type is NubRefType) + { + _writer.WriteLine($"rc_retain({value});"); + _writer.WriteLine($"rc_release({target});"); + } + _writer.WriteLine($"{target} = {value};"); } @@ -192,11 +214,6 @@ public class Generator _writer.WriteLine("continue;"); } - private void EmitDefer(DeferNode deferNode) - { - _deferStack.Peek().Add(deferNode); - } - private void EmitForSlice(ForSliceNode forSliceNode) { var targetType = (NubSliceType)forSliceNode.Target.Type; @@ -207,8 +224,11 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - _writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementNameToken.Value)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];"); - EmitBlock(forSliceNode.Body); + using (BeginScope()) + { + _writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementNameToken.Value)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];"); + EmitBlock(forSliceNode.Body); + } } _writer.WriteLine("}"); @@ -224,8 +244,11 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - _writer.WriteLine($"{CType.Create(targetType.ElementType, forConstArrayNode.ElementNameToken.Value)} = {target}[{indexName}];"); - EmitBlock(forConstArrayNode.Body); + using (BeginScope()) + { + _writer.WriteLine($"{CType.Create(targetType.ElementType, forConstArrayNode.ElementNameToken.Value)} = {target}[{indexName}];"); + EmitBlock(forConstArrayNode.Body); + } } _writer.WriteLine("}"); @@ -238,7 +261,10 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - EmitBlock(ifNode.Body); + using (BeginScope()) + { + EmitBlock(ifNode.Body); + } } _writer.WriteLine("}"); @@ -251,7 +277,10 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - EmitBlock(elseNode); + using (BeginScope()) + { + EmitBlock(elseNode); + } } _writer.WriteLine("}"); @@ -263,39 +292,20 @@ public class Generator { if (returnNode.Value == null) { - var blockDefers = _deferStack.Peek(); - for (var i = blockDefers.Count - 1; i >= 0; i--) - { - EmitStatement(blockDefers[i].Statement); - } - - var refCleanups = _refCleanupStack.Peek(); - foreach (var refCleanup in refCleanups) - { - _writer.WriteLine($"rc_release({refCleanup});"); - } - + EmitScopeCleanup(); _writer.WriteLine("return;"); } else { var returnValue = EmitExpression(returnNode.Value); - var tmp = NewTmp(); _writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};"); - - var blockDefers = _deferStack.Peek(); - for (var i = blockDefers.Count - 1; i >= 0; i--) + if (returnNode.Value.Type is NubRefType) { - EmitStatement(blockDefers[i].Statement); - } - - var refCleanups = _refCleanupStack.Peek(); - foreach (var refCleanup in refCleanups) - { - _writer.WriteLine($"rc_release({refCleanup});"); + _writer.WriteLine($"rc_retain({tmp});"); } + EmitScopeCleanup(); EmitLine(returnNode.Tokens.FirstOrDefault()); _writer.WriteLine($"return {tmp};"); } @@ -313,6 +323,10 @@ public class Generator { var value = EmitExpression(variableDeclarationNode.Assignment); _writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)} = {value};"); + if (variableDeclarationNode.Type is NubRefType) + { + _writer.WriteLine($"rc_retain({variableDeclarationNode.NameToken.Value});"); + } } else { @@ -327,7 +341,10 @@ public class Generator _writer.WriteLine("{"); using (_writer.Indent()) { - EmitBlock(whileNode.Body); + using (BeginScope()) + { + EmitBlock(whileNode.Body); + } } _writer.WriteLine("}"); @@ -492,7 +509,19 @@ public class Generator private string EmitFuncCall(FuncCallNode funcCallNode) { var name = EmitExpression(funcCallNode.Expression); - var parameterNames = funcCallNode.Parameters.Select(EmitExpression).ToList(); + + var parameterNames = new List(); + foreach (var parameter in funcCallNode.Parameters) + { + var result = EmitExpression(parameter); + if (parameter.Type is NubRefType) + { + _writer.WriteLine($"rc_retain({result});"); + } + + parameterNames.Add(result); + } + return $"{name}({string.Join(", ", parameterNames)})"; } @@ -529,7 +558,7 @@ public class Generator _writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{initString}}};"); - _refCleanupStack.Peek().Add(tmp); + Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});")); return tmp; } @@ -625,24 +654,45 @@ public class Generator private void EmitBlock(BlockNode blockNode) { - _deferStack.Push([]); - _refCleanupStack.Push([]); - foreach (var statementNode in blockNode.Statements) { EmitStatement(statementNode); } + } - var blockDefers = _deferStack.Pop(); - for (var i = blockDefers.Count - 1; i >= 0; i--) + private void EmitScopeCleanup() + { + var deferredStack = Scope.GetDeferred(); + while (deferredStack.TryPop(out var deferred)) { - EmitStatement(blockDefers[i].Statement); - } - - var refCleanups = _refCleanupStack.Pop(); - foreach (var refCleanup in refCleanups) - { - _writer.WriteLine($"rc_release({refCleanup});"); + deferred.Invoke(); } } + + private ScopeDisposer BeginScope() + { + _scopes.Push(new Scope()); + return new ScopeDisposer(this); + } + + private sealed class ScopeDisposer(Generator owner) : IDisposable + { + public void Dispose() + { + owner.EmitScopeCleanup(); + owner._scopes.Pop(); + } + } +} + +public class Scope +{ + private readonly List _deferred = []; + + public void Defer(Action action) + { + _deferred.Add(action); + } + + public Stack GetDeferred() => new(_deferred); } \ No newline at end of file diff --git a/examples/playgroud/main.nub b/examples/playgroud/main.nub index 6e14781..2325235 100644 --- a/examples/playgroud/main.nub +++ b/examples/playgroud/main.nub @@ -16,5 +16,12 @@ extern "main" func main(argc: i64, argv: [?]^i8): i64 } puts(x^.name) + + test(x) + return 0 +} + +func test(x: &Human) +{ } \ No newline at end of file diff --git a/runtime/ref.c b/runtime/ref.c index 17ab78b..93a674c 100644 --- a/runtime/ref.c +++ b/runtime/ref.c @@ -12,7 +12,7 @@ void *rc_alloc(size_t size, void (*destructor)(void *self)) exit(69); } - header->ref_count = 1; + header->ref_count = 0; header->destructor = destructor; return (void *)(header + 1); @@ -29,7 +29,7 @@ void rc_release(void *obj) { ref_header *header = ((ref_header *)obj) - 1; printf("rc_release\n"); - if (--header->ref_count == 0) + if (--header->ref_count <= 0) { if (header->destructor) {