...
This commit is contained in:
@@ -7,14 +7,14 @@ namespace NubLang.Generation;
|
||||
|
||||
public class Generator
|
||||
{
|
||||
private readonly CompilationUnit _compilationUnit;
|
||||
private readonly List<TopLevelNode> _compilationUnit;
|
||||
private readonly IndentedTextWriter _writer;
|
||||
private readonly Stack<Scope> _scopes = [];
|
||||
private int _tmpIndex;
|
||||
|
||||
private Scope Scope => _scopes.Peek();
|
||||
|
||||
public Generator(CompilationUnit compilationUnit)
|
||||
public Generator(List<TopLevelNode> compilationUnit)
|
||||
{
|
||||
_compilationUnit = compilationUnit;
|
||||
_writer = new IndentedTextWriter();
|
||||
@@ -31,66 +31,51 @@ public class Generator
|
||||
return externSymbol ?? $"{module}_{name}";
|
||||
}
|
||||
|
||||
private string GetModuleName()
|
||||
{
|
||||
return _compilationUnit.OfType<ModuleNode>().First().NameToken.Value;
|
||||
}
|
||||
|
||||
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;
|
||||
char *data;
|
||||
};
|
||||
|
||||
struct nub_slice
|
||||
{
|
||||
unsigned long long length;
|
||||
void *data;
|
||||
};
|
||||
|
||||
""");
|
||||
|
||||
foreach (var (_, structTypes) in _compilationUnit.ImportedStructTypes)
|
||||
foreach (var structType in _compilationUnit.OfType<StructNode>())
|
||||
{
|
||||
foreach (var structType in structTypes)
|
||||
_writer.WriteLine($"void {CType.Create(structType.StructType)}_create({CType.Create(structType.StructType)} *self)");
|
||||
_writer.WriteLine("{");
|
||||
using (_writer.Indent())
|
||||
{
|
||||
_writer.WriteLine(CType.Create(structType));
|
||||
_writer.WriteLine("{");
|
||||
using (_writer.Indent())
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
foreach (var field in structType.Fields)
|
||||
if (field.Value != null)
|
||||
{
|
||||
_writer.WriteLine($"{CType.Create(field.Type, field.Name, constArraysAsPointers: false)};");
|
||||
var value = EmitExpression(field.Value);
|
||||
_writer.WriteLine($"self->{field.NameToken.Value} = {value}");
|
||||
}
|
||||
}
|
||||
|
||||
_writer.WriteLine("};");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
// note(nub31): Forward declarations
|
||||
foreach (var (module, prototypes) in _compilationUnit.ImportedFunctions)
|
||||
{
|
||||
foreach (var prototype in prototypes)
|
||||
_writer.WriteLine("}");
|
||||
_writer.WriteLine();
|
||||
|
||||
_writer.WriteLine($"void {CType.Create(structType.StructType)}_destroy({CType.Create(structType.StructType)} *self)");
|
||||
_writer.WriteLine("{");
|
||||
using (_writer.Indent())
|
||||
{
|
||||
EmitLine(prototype.Tokens.FirstOrDefault());
|
||||
var parameters = prototype.Parameters.Count != 0
|
||||
? string.Join(", ", prototype.Parameters.Select(x => CType.Create(x.Type, x.NameToken.Value)))
|
||||
: "void";
|
||||
|
||||
var name = FuncName(module.Value, prototype.NameToken.Value, prototype.ExternSymbolToken?.Value);
|
||||
_writer.WriteLine($"{CType.Create(prototype.ReturnType, name)}({parameters});");
|
||||
_writer.WriteLine();
|
||||
foreach (var field in structType.Fields)
|
||||
{
|
||||
if (field.Type is NubRefType)
|
||||
{
|
||||
_writer.WriteLine($"rc_release(self->{field.NameToken.Value});");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_writer.WriteLine("}");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
// note(nub31): Normal functions
|
||||
foreach (var funcNode in _compilationUnit.Functions)
|
||||
foreach (var funcNode in _compilationUnit.OfType<FuncNode>())
|
||||
{
|
||||
if (funcNode.Body == null) continue;
|
||||
|
||||
@@ -99,7 +84,7 @@ public class Generator
|
||||
? string.Join(", ", funcNode.Prototype.Parameters.Select(x => CType.Create(x.Type, x.NameToken.Value)))
|
||||
: "void";
|
||||
|
||||
var name = FuncName(_compilationUnit.Module.Value, funcNode.NameToken.Value, funcNode.Prototype.ExternSymbolToken?.Value);
|
||||
var name = FuncName(GetModuleName(), funcNode.NameToken.Value, funcNode.Prototype.ExternSymbolToken?.Value);
|
||||
_writer.WriteLine($"{CType.Create(funcNode.Prototype.ReturnType, name)}({parameters})");
|
||||
_writer.WriteLine("{");
|
||||
using (_writer.Indent())
|
||||
@@ -314,8 +299,7 @@ public class Generator
|
||||
|
||||
private void EmitStatementFuncCall(StatementFuncCallNode statementFuncCallNode)
|
||||
{
|
||||
var funcCall = EmitFuncCall(statementFuncCallNode.FuncCall);
|
||||
_writer.WriteLine($"{funcCall};");
|
||||
EmitFuncCall(statementFuncCallNode.FuncCall);
|
||||
}
|
||||
|
||||
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
|
||||
@@ -526,7 +510,16 @@ public class Generator
|
||||
parameterNames.Add(result);
|
||||
}
|
||||
|
||||
return $"{name}({string.Join(", ", parameterNames)})";
|
||||
var tmp = NewTmp();
|
||||
|
||||
_writer.WriteLine($"{CType.Create(funcCallNode.Type)} {tmp} = {name}({string.Join(", ", parameterNames)});");
|
||||
|
||||
if (funcCallNode.Type is NubRefType)
|
||||
{
|
||||
Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});"));
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private string EmitAddressOf(AddressOfNode addressOfNode)
|
||||
@@ -547,22 +540,18 @@ public class Generator
|
||||
var structType = (NubStructType)type.BaseType;
|
||||
|
||||
var tmp = NewTmp();
|
||||
_writer.WriteLine($"{CType.Create(type)} {tmp} = ({CType.Create(type)})rc_alloc(sizeof({CType.Create(structType)}), NULL);");
|
||||
_writer.WriteLine($"{CType.Create(type)} {tmp} = ({CType.Create(type)})rc_alloc(sizeof({CType.Create(structType)}), (void (*)(void *)){CType.Create(structType)}_destroy);");
|
||||
Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});"));
|
||||
|
||||
var initValues = new List<string>();
|
||||
_writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{0}}};");
|
||||
_writer.WriteLine($"{CType.Create(structType)}_create({tmp});");
|
||||
|
||||
foreach (var initializer in refStructInitializerNode.Initializers)
|
||||
{
|
||||
var value = EmitExpression(initializer.Value);
|
||||
initValues.Add($".{initializer.Key.Value} = {value}");
|
||||
_writer.WriteLine($"{tmp}->{initializer.Key} = {value};");
|
||||
}
|
||||
|
||||
var initString = initValues.Count == 0
|
||||
? "0"
|
||||
: string.Join(", ", initValues);
|
||||
|
||||
_writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{initString}}};");
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -578,7 +567,7 @@ public class Generator
|
||||
private string EmitStringLiteral(StringLiteralNode stringLiteralNode)
|
||||
{
|
||||
var length = Encoding.UTF8.GetByteCount(stringLiteralNode.Value);
|
||||
return $"(nub_string){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}";
|
||||
return $"({CType.Create(stringLiteralNode.Type)}){{.length = {length}, .data = \"{stringLiteralNode.Value}\"}}";
|
||||
}
|
||||
|
||||
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccessNode)
|
||||
@@ -589,18 +578,19 @@ public class Generator
|
||||
|
||||
private string EmitStructInitializer(StructInitializerNode structInitializerNode)
|
||||
{
|
||||
var initValues = new List<string>();
|
||||
var structType = (NubStructType)structInitializerNode.Type;
|
||||
|
||||
var tmp = NewTmp();
|
||||
_writer.WriteLine($"{CType.Create(structType)} {tmp} = ({CType.Create(structType)}){{0}};");
|
||||
_writer.WriteLine($"{CType.Create(structType)}_create(&{tmp});");
|
||||
|
||||
foreach (var initializer in structInitializerNode.Initializers)
|
||||
{
|
||||
var value = EmitExpression(initializer.Value);
|
||||
initValues.Add($".{initializer.Key.Value} = {value}");
|
||||
_writer.WriteLine($"{tmp}.{initializer.Key} = {value};");
|
||||
}
|
||||
|
||||
var initString = initValues.Count == 0
|
||||
? "0"
|
||||
: string.Join(", ", initValues);
|
||||
|
||||
return $"({CType.Create(structInitializerNode.Type)}){{{initString}}}";
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private string EmitI8Literal(I8LiteralNode i8LiteralNode)
|
||||
|
||||
Reference in New Issue
Block a user