This commit is contained in:
nub31
2025-10-26 16:07:49 +01:00
parent 828e20ddb6
commit 3febaaea81
15 changed files with 256 additions and 44 deletions

View File

@@ -10,6 +10,7 @@ public class Generator
private readonly CompilationUnit _compilationUnit;
private readonly IndentedTextWriter _writer;
private readonly Stack<List<DeferNode>> _deferStack = [];
private readonly Stack<List<string>> _refCleanupStack = [];
private int _tmpIndex;
public Generator(CompilationUnit compilationUnit)
@@ -32,6 +33,12 @@ public class Generator
public string Emit()
{
_writer.WriteLine("""
#include <stddef.h>
void *rc_alloc(size_t size, void (*destructor)(void *self));
void rc_retain(void *obj);
void rc_release(void *obj);
struct nub_string
{
unsigned long long length;
@@ -262,31 +269,35 @@ public class Generator
EmitStatement(blockDefers[i].Statement);
}
var refCleanups = _refCleanupStack.Peek();
foreach (var refCleanup in refCleanups)
{
_writer.WriteLine($"rc_release({refCleanup});");
}
_writer.WriteLine("return;");
}
else
{
var returnValue = EmitExpression(returnNode.Value);
if (_deferStack.Peek().Count != 0)
{
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(returnNode.Value.Type, tmp)} = {returnValue};");
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--)
{
EmitStatement(blockDefers[i].Statement);
}
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};");
}
else
var blockDefers = _deferStack.Peek();
for (var i = blockDefers.Count - 1; i >= 0; i--)
{
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {returnValue};");
EmitStatement(blockDefers[i].Statement);
}
var refCleanups = _refCleanupStack.Peek();
foreach (var refCleanup in refCleanups)
{
_writer.WriteLine($"rc_release({refCleanup});");
}
EmitLine(returnNode.Tokens.FirstOrDefault());
_writer.WriteLine($"return {tmp};");
}
}
@@ -345,6 +356,8 @@ public class Generator
FuncCallNode funcCallNode => EmitFuncCall(funcCallNode),
FuncIdentifierNode funcIdentifierNode => FuncName(funcIdentifierNode.ModuleToken.Value, funcIdentifierNode.NameToken.Value, funcIdentifierNode.ExternSymbolToken?.Value),
AddressOfNode addressOfNode => EmitAddressOf(addressOfNode),
RefDereferenceNode refDereferenceNode => EmitRefDereference(refDereferenceNode),
RefStructInitializerNode refStructInitializerNode => EmitRefStructInitializer(refStructInitializerNode),
SizeNode sizeBuiltinNode => $"sizeof({CType.Create(sizeBuiltinNode.TargetType)})",
SliceIndexAccessNode sliceIndexAccessNode => EmitSliceArrayIndexAccess(sliceIndexAccessNode),
StringLiteralNode stringLiteralNode => EmitStringLiteral(stringLiteralNode),
@@ -489,6 +502,38 @@ public class Generator
return $"&{value}";
}
private string EmitRefDereference(RefDereferenceNode refDereferenceNode)
{
var pointer = EmitExpression(refDereferenceNode.Target);
return $"*{pointer}";
}
private string EmitRefStructInitializer(RefStructInitializerNode refStructInitializerNode)
{
var type = (NubRefType)refStructInitializerNode.Type;
var structType = (NubStructType)type.BaseType;
var tmp = NewTmp();
_writer.WriteLine($"{CType.Create(type)} {tmp} = ({CType.Create(type)})rc_alloc(sizeof({CType.Create(structType)}), NULL);");
var initValues = new List<string>();
foreach (var initializer in refStructInitializerNode.Initializers)
{
var value = EmitExpression(initializer.Value);
initValues.Add($".{initializer.Key.Value} = {value}");
}
var initString = initValues.Count == 0
? "0"
: string.Join(", ", initValues);
_writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{initString}}};");
_refCleanupStack.Peek().Add(tmp);
return tmp;
}
private string EmitSliceArrayIndexAccess(SliceIndexAccessNode sliceIndexAccessNode)
{
var targetType = (NubSliceType)sliceIndexAccessNode.Target.Type;
@@ -581,6 +626,7 @@ public class Generator
private void EmitBlock(BlockNode blockNode)
{
_deferStack.Push([]);
_refCleanupStack.Push([]);
foreach (var statementNode in blockNode.Statements)
{
@@ -592,5 +638,11 @@ public class Generator
{
EmitStatement(blockDefers[i].Statement);
}
var refCleanups = _refCleanupStack.Pop();
foreach (var refCleanup in refCleanups)
{
_writer.WriteLine($"rc_release({refCleanup});");
}
}
}