Refs working?

This commit is contained in:
nub31
2025-10-26 17:05:56 +01:00
parent 3febaaea81
commit d11df414ad
3 changed files with 113 additions and 56 deletions

View File

@@ -9,10 +9,11 @@ public class Generator
{ {
private readonly CompilationUnit _compilationUnit; private readonly CompilationUnit _compilationUnit;
private readonly IndentedTextWriter _writer; private readonly IndentedTextWriter _writer;
private readonly Stack<List<DeferNode>> _deferStack = []; private readonly Stack<Scope> _scopes = [];
private readonly Stack<List<string>> _refCleanupStack = [];
private int _tmpIndex; private int _tmpIndex;
private Scope Scope => _scopes.Peek();
public Generator(CompilationUnit compilationUnit) public Generator(CompilationUnit compilationUnit)
{ {
_compilationUnit = compilationUnit; _compilationUnit = compilationUnit;
@@ -103,8 +104,19 @@ public class Generator
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{ {
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); EmitBlock(funcNode.Body);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
_writer.WriteLine(); _writer.WriteLine();
@@ -124,9 +136,12 @@ public class Generator
case BlockNode blockNode: case BlockNode blockNode:
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{
using (BeginScope())
{ {
EmitBlock(blockNode); EmitBlock(blockNode);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
break; break;
@@ -137,7 +152,7 @@ public class Generator
EmitContinue(continueNode); EmitContinue(continueNode);
break; break;
case DeferNode deferNode: case DeferNode deferNode:
EmitDefer(deferNode); Scope.Defer(() => EmitStatement(deferNode.Statement));
break; break;
case ForConstArrayNode forConstArrayNode: case ForConstArrayNode forConstArrayNode:
EmitForConstArray(forConstArrayNode); EmitForConstArray(forConstArrayNode);
@@ -177,6 +192,13 @@ public class Generator
{ {
var target = EmitExpression(assignmentNode.Target); var target = EmitExpression(assignmentNode.Target);
var value = EmitExpression(assignmentNode.Value); 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};"); _writer.WriteLine($"{target} = {value};");
} }
@@ -192,11 +214,6 @@ public class Generator
_writer.WriteLine("continue;"); _writer.WriteLine("continue;");
} }
private void EmitDefer(DeferNode deferNode)
{
_deferStack.Peek().Add(deferNode);
}
private void EmitForSlice(ForSliceNode forSliceNode) private void EmitForSlice(ForSliceNode forSliceNode)
{ {
var targetType = (NubSliceType)forSliceNode.Target.Type; var targetType = (NubSliceType)forSliceNode.Target.Type;
@@ -206,10 +223,13 @@ public class Generator
_writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {target}.length; ++{indexName})"); _writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {target}.length; ++{indexName})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{
using (BeginScope())
{ {
_writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementNameToken.Value)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];"); _writer.WriteLine($"{CType.Create(targetType.ElementType, forSliceNode.ElementNameToken.Value)} = (({CType.Create(targetType.ElementType)}*){target}.data)[{indexName}];");
EmitBlock(forSliceNode.Body); EmitBlock(forSliceNode.Body);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
} }
@@ -223,10 +243,13 @@ public class Generator
_writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {targetType.Size}; ++{indexName})"); _writer.WriteLine($"for (unsigned long long {indexName} = 0; {indexName} < {targetType.Size}; ++{indexName})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{
using (BeginScope())
{ {
_writer.WriteLine($"{CType.Create(targetType.ElementType, forConstArrayNode.ElementNameToken.Value)} = {target}[{indexName}];"); _writer.WriteLine($"{CType.Create(targetType.ElementType, forConstArrayNode.ElementNameToken.Value)} = {target}[{indexName}];");
EmitBlock(forConstArrayNode.Body); EmitBlock(forConstArrayNode.Body);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
} }
@@ -237,9 +260,12 @@ public class Generator
_writer.WriteLine($"{(elseIf ? "else " : "")}if ({condition})"); _writer.WriteLine($"{(elseIf ? "else " : "")}if ({condition})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{
using (BeginScope())
{ {
EmitBlock(ifNode.Body); EmitBlock(ifNode.Body);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
ifNode.Else?.Match ifNode.Else?.Match
@@ -250,9 +276,12 @@ public class Generator
_writer.WriteLine("else"); _writer.WriteLine("else");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{
using (BeginScope())
{ {
EmitBlock(elseNode); EmitBlock(elseNode);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
} }
@@ -263,39 +292,20 @@ public class Generator
{ {
if (returnNode.Value == null) if (returnNode.Value == null)
{ {
var blockDefers = _deferStack.Peek(); EmitScopeCleanup();
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});");
}
_writer.WriteLine("return;"); _writer.WriteLine("return;");
} }
else else
{ {
var returnValue = EmitExpression(returnNode.Value); var returnValue = EmitExpression(returnNode.Value);
var tmp = NewTmp(); var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};"); _writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};");
if (returnNode.Value.Type is NubRefType)
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{ {
EmitStatement(blockDefers[i].Statement); _writer.WriteLine($"rc_retain({tmp});");
}
var refCleanups = _refCleanupStack.Peek();
foreach (var refCleanup in refCleanups)
{
_writer.WriteLine($"rc_release({refCleanup});");
} }
EmitScopeCleanup();
EmitLine(returnNode.Tokens.FirstOrDefault()); EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};"); _writer.WriteLine($"return {tmp};");
} }
@@ -313,6 +323,10 @@ public class Generator
{ {
var value = EmitExpression(variableDeclarationNode.Assignment); var value = EmitExpression(variableDeclarationNode.Assignment);
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)} = {value};"); _writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)} = {value};");
if (variableDeclarationNode.Type is NubRefType)
{
_writer.WriteLine($"rc_retain({variableDeclarationNode.NameToken.Value});");
}
} }
else else
{ {
@@ -326,9 +340,12 @@ public class Generator
_writer.WriteLine($"while ({condition})"); _writer.WriteLine($"while ({condition})");
_writer.WriteLine("{"); _writer.WriteLine("{");
using (_writer.Indent()) using (_writer.Indent())
{
using (BeginScope())
{ {
EmitBlock(whileNode.Body); EmitBlock(whileNode.Body);
} }
}
_writer.WriteLine("}"); _writer.WriteLine("}");
} }
@@ -492,7 +509,19 @@ public class Generator
private string EmitFuncCall(FuncCallNode funcCallNode) private string EmitFuncCall(FuncCallNode funcCallNode)
{ {
var name = EmitExpression(funcCallNode.Expression); var name = EmitExpression(funcCallNode.Expression);
var parameterNames = funcCallNode.Parameters.Select(EmitExpression).ToList();
var parameterNames = new List<string>();
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)})"; return $"{name}({string.Join(", ", parameterNames)})";
} }
@@ -529,7 +558,7 @@ public class Generator
_writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{initString}}};"); _writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{initString}}};");
_refCleanupStack.Peek().Add(tmp); Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});"));
return tmp; return tmp;
} }
@@ -625,24 +654,45 @@ public class Generator
private void EmitBlock(BlockNode blockNode) private void EmitBlock(BlockNode blockNode)
{ {
_deferStack.Push([]);
_refCleanupStack.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);
} }
var refCleanups = _refCleanupStack.Pop(); private void EmitScopeCleanup()
foreach (var refCleanup in refCleanups)
{ {
_writer.WriteLine($"rc_release({refCleanup});"); var deferredStack = Scope.GetDeferred();
while (deferredStack.TryPop(out var deferred))
{
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<Action> _deferred = [];
public void Defer(Action action)
{
_deferred.Add(action);
}
public Stack<Action> GetDeferred() => new(_deferred);
}

View File

@@ -16,5 +16,12 @@ extern "main" func main(argc: i64, argv: [?]^i8): i64
} }
puts(x^.name) puts(x^.name)
test(x)
return 0 return 0
} }
func test(x: &Human)
{
}

View File

@@ -12,7 +12,7 @@ void *rc_alloc(size_t size, void (*destructor)(void *self))
exit(69); exit(69);
} }
header->ref_count = 1; header->ref_count = 0;
header->destructor = destructor; header->destructor = destructor;
return (void *)(header + 1); return (void *)(header + 1);
@@ -29,7 +29,7 @@ void rc_release(void *obj)
{ {
ref_header *header = ((ref_header *)obj) - 1; ref_header *header = ((ref_header *)obj) - 1;
printf("rc_release\n"); printf("rc_release\n");
if (--header->ref_count == 0) if (--header->ref_count <= 0)
{ {
if (header->destructor) if (header->destructor)
{ {