ref
This commit is contained in:
@@ -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});");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user