...
This commit is contained in:
@@ -48,39 +48,13 @@ Directory.CreateDirectory(".build");
|
|||||||
|
|
||||||
var typedModules = modules.Select(x => (x.Key, TypedModule.FromModule(x.Key, x.Value, modules))).ToDictionary();
|
var typedModules = modules.Select(x => (x.Key, TypedModule.FromModule(x.Key, x.Value, modules))).ToDictionary();
|
||||||
|
|
||||||
var moduleHeaders = new List<string>();
|
Directory.CreateDirectory(Path.Combine(".build", "modules"));
|
||||||
|
|
||||||
var commonHeaderOut = Path.Combine(".build", "runtime.h");
|
|
||||||
|
|
||||||
File.WriteAllText(commonHeaderOut, """
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
void *rc_alloc(size_t size, void (*destructor)(void *self));
|
|
||||||
void rc_retain(void *obj);
|
|
||||||
void rc_release(void *obj);
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned long long length;
|
|
||||||
char *data;
|
|
||||||
} nub_string;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
unsigned long long length;
|
|
||||||
void *data;
|
|
||||||
} nub_slice;
|
|
||||||
""");
|
|
||||||
|
|
||||||
moduleHeaders.Add(commonHeaderOut);
|
|
||||||
|
|
||||||
foreach (var typedModule in typedModules)
|
foreach (var typedModule in typedModules)
|
||||||
{
|
{
|
||||||
var header = HeaderGenerator.Generate(typedModule.Key, typedModule.Value);
|
var header = HeaderGenerator.Generate(typedModule.Key, typedModule.Value);
|
||||||
var headerOut = Path.Combine(".build", "modules", typedModule.Key + ".h");
|
var headerOut = Path.Combine(Path.Combine(".build", "modules"), typedModule.Key + ".h");
|
||||||
Directory.CreateDirectory(Path.Combine(".build", "modules"));
|
|
||||||
File.WriteAllText(headerOut, header);
|
File.WriteAllText(headerOut, header);
|
||||||
moduleHeaders.Add(headerOut);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < args.Length; i++)
|
for (var i = 0; i < args.Length; i++)
|
||||||
@@ -106,7 +80,7 @@ foreach (var cPath in cPaths)
|
|||||||
{
|
{
|
||||||
var objectPath = Path.ChangeExtension(cPath, "o");
|
var objectPath = Path.ChangeExtension(cPath, "o");
|
||||||
using var compileProcess = Process.Start("clang", [
|
using var compileProcess = Process.Start("clang", [
|
||||||
..moduleHeaders.SelectMany(x => new[] { "-include", x }),
|
"-I.build",
|
||||||
"-ffreestanding", "-std=c23",
|
"-ffreestanding", "-std=c23",
|
||||||
"-g", "-c",
|
"-g", "-c",
|
||||||
"-o", objectPath,
|
"-o", objectPath,
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ public static class CType
|
|||||||
NubConstArrayType a => CreateConstArrayType(a, variableName, constArraysAsPointers),
|
NubConstArrayType a => CreateConstArrayType(a, variableName, constArraysAsPointers),
|
||||||
NubArrayType a => CreateArrayType(a, variableName),
|
NubArrayType a => CreateArrayType(a, variableName),
|
||||||
NubFuncType f => CreateFuncType(f, variableName),
|
NubFuncType f => CreateFuncType(f, variableName),
|
||||||
NubStructType s => $"{s.Module}_{s.Name}_{NameMangler.Mangle(s)}" + (variableName != null ? $" {variableName}" : ""),
|
// NubStructType s => $"{s.Module}_{s.Name}_{NameMangler.Mangle(s)}" + (variableName != null ? $" {variableName}" : ""),
|
||||||
|
NubStructType s => $"{s.Module}_{s.Name}" + (variableName != null ? $" {variableName}" : ""),
|
||||||
_ => throw new NotSupportedException($"C type generation not supported for: {type}")
|
_ => throw new NotSupportedException($"C type generation not supported for: {type}")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -60,12 +61,12 @@ public static class CType
|
|||||||
return baseType + "*" + (varName != null ? $" {varName}" : "");
|
return baseType + "*" + (varName != null ? $" {varName}" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string CreateConstArrayType(NubConstArrayType arr, string? varName, bool inStructDef)
|
private static string CreateConstArrayType(NubConstArrayType arr, string? varName, bool constArraysAsPointers)
|
||||||
{
|
{
|
||||||
var elementType = Create(arr.ElementType);
|
var elementType = Create(arr.ElementType);
|
||||||
|
|
||||||
// Treat const arrays as pointers unless in a struct definition
|
// Treat const arrays as pointers unless in a struct definition
|
||||||
if (!inStructDef)
|
if (constArraysAsPointers)
|
||||||
{
|
{
|
||||||
return elementType + "*" + (varName != null ? $" {varName}" : "");
|
return elementType + "*" + (varName != null ? $" {varName}" : "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,34 @@ public class Generator
|
|||||||
|
|
||||||
public string Emit()
|
public string Emit()
|
||||||
{
|
{
|
||||||
|
foreach (var importNode in _compilationUnit.OfType<ImportNode>())
|
||||||
|
{
|
||||||
|
_writer.WriteLine($"#include <modules/{importNode.NameToken.Value}.h>");
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine($"#include <modules/{GetModuleName()}.h>");
|
||||||
|
|
||||||
|
_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);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned long long length;
|
||||||
|
char *data;
|
||||||
|
} nub_string;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned long long length;
|
||||||
|
void *data;
|
||||||
|
} nub_slice;
|
||||||
|
|
||||||
|
""");
|
||||||
|
|
||||||
foreach (var structType in _compilationUnit.OfType<StructNode>())
|
foreach (var structType in _compilationUnit.OfType<StructNode>())
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"void {CType.Create(structType.StructType)}_create({CType.Create(structType.StructType)} *self)");
|
_writer.WriteLine($"void {CType.Create(structType.StructType)}_create({CType.Create(structType.StructType)} *self)");
|
||||||
@@ -50,6 +78,7 @@ public class Generator
|
|||||||
{
|
{
|
||||||
var value = EmitExpression(field.Value);
|
var value = EmitExpression(field.Value);
|
||||||
_writer.WriteLine($"self->{field.NameToken.Value} = {value}");
|
_writer.WriteLine($"self->{field.NameToken.Value} = {value}");
|
||||||
|
EmitConstructor($"self->{field.NameToken.Value}", field.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +94,18 @@ public class Generator
|
|||||||
{
|
{
|
||||||
if (field.Type is NubRefType)
|
if (field.Type is NubRefType)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"rc_release(self->{field.NameToken.Value});");
|
_writer.WriteLine($"if (self->{field.NameToken.Value})");
|
||||||
|
_writer.WriteLine("{");
|
||||||
|
using (_writer.Indent())
|
||||||
|
{
|
||||||
|
EmitDestructor($"self->{field.NameToken.Value}", field.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine("}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitDestructor($"self->{field.NameToken.Value}", field.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,6 +153,7 @@ public class Generator
|
|||||||
private void EmitStatement(StatementNode statementNode)
|
private void EmitStatement(StatementNode statementNode)
|
||||||
{
|
{
|
||||||
EmitLine(statementNode.Tokens.FirstOrDefault());
|
EmitLine(statementNode.Tokens.FirstOrDefault());
|
||||||
|
|
||||||
switch (statementNode)
|
switch (statementNode)
|
||||||
{
|
{
|
||||||
case AssignmentNode assignmentNode:
|
case AssignmentNode assignmentNode:
|
||||||
@@ -167,10 +208,10 @@ public class Generator
|
|||||||
|
|
||||||
private void EmitLine(Token? token)
|
private void EmitLine(Token? token)
|
||||||
{
|
{
|
||||||
if (token == null) return;
|
// if (token == null) return;
|
||||||
var file = token.Span.FilePath;
|
// var file = token.Span.FilePath;
|
||||||
var line = token.Span.Start.Line;
|
// var line = token.Span.Start.Line;
|
||||||
_writer.WriteLine($"#line {line} \"{file}\"");
|
// _writer.WriteLine($"#line {line} \"{file}\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitAssignment(AssignmentNode assignmentNode)
|
private void EmitAssignment(AssignmentNode assignmentNode)
|
||||||
@@ -181,7 +222,6 @@ public class Generator
|
|||||||
if (assignmentNode.Target.Type is NubRefType)
|
if (assignmentNode.Target.Type is NubRefType)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"rc_retain({value});");
|
_writer.WriteLine($"rc_retain({value});");
|
||||||
Scope.Defer(() => _writer.WriteLine($"rc_release({value});"));
|
|
||||||
_writer.WriteLine($"rc_release({target});");
|
_writer.WriteLine($"rc_release({target});");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,17 +344,18 @@ public class Generator
|
|||||||
|
|
||||||
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
|
private void EmitVariableDeclaration(VariableDeclarationNode variableDeclarationNode)
|
||||||
{
|
{
|
||||||
|
Scope.AddVariable(variableDeclarationNode.NameToken.Value, variableDeclarationNode.Type);
|
||||||
|
|
||||||
if (variableDeclarationNode.Assignment != null)
|
if (variableDeclarationNode.Assignment != null)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(variableDeclarationNode.Assignment);
|
var value = EmitExpression(variableDeclarationNode.Assignment);
|
||||||
|
|
||||||
|
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)} = {value};");
|
||||||
|
|
||||||
if (variableDeclarationNode.Type is NubRefType)
|
if (variableDeclarationNode.Type is NubRefType)
|
||||||
{
|
{
|
||||||
_writer.WriteLine($"rc_retain({value});");
|
_writer.WriteLine($"rc_retain({variableDeclarationNode.NameToken.Value});");
|
||||||
Scope.Defer(() => _writer.WriteLine($"rc_release({value});"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.WriteLine($"{CType.Create(variableDeclarationNode.Type, variableDeclarationNode.NameToken.Value)} = {value};");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -444,14 +485,18 @@ public class Generator
|
|||||||
|
|
||||||
private string EmitConstArrayInitializer(ConstArrayInitializerNode arrayInitializerNode)
|
private string EmitConstArrayInitializer(ConstArrayInitializerNode arrayInitializerNode)
|
||||||
{
|
{
|
||||||
var values = new List<string>();
|
var arrayType = (NubConstArrayType)arrayInitializerNode.Type;
|
||||||
foreach (var value in arrayInitializerNode.Values)
|
|
||||||
|
var tmp = NewTmp();
|
||||||
|
_writer.WriteLine($"{CType.Create(arrayType.ElementType)} {tmp}[{arrayType.Size}] = {{0}};");
|
||||||
|
|
||||||
|
for (var i = 0; i < arrayInitializerNode.Values.Count; i++)
|
||||||
{
|
{
|
||||||
values.Add(EmitExpression(value));
|
var valueName = EmitExpression(arrayInitializerNode.Values[i]);
|
||||||
|
_writer.WriteLine($"{tmp}[{i}] = {valueName};");
|
||||||
}
|
}
|
||||||
|
|
||||||
var arrayType = (NubConstArrayType)arrayInitializerNode.Type;
|
return tmp;
|
||||||
return $"({CType.Create(arrayType.ElementType)}[{arrayType.Size}]){{{string.Join(", ", values)}}}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitDereference(DereferenceNode dereferenceNode)
|
private string EmitDereference(DereferenceNode dereferenceNode)
|
||||||
@@ -543,13 +588,16 @@ public class Generator
|
|||||||
_writer.WriteLine($"{CType.Create(type)} {tmp} = ({CType.Create(type)})rc_alloc(sizeof({CType.Create(structType)}), (void (*)(void *)){CType.Create(structType)}_destroy);");
|
_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});"));
|
Scope.Defer(() => _writer.WriteLine($"rc_release({tmp});"));
|
||||||
|
|
||||||
_writer.WriteLine($"*{tmp} = ({CType.Create(structType)}){{{0}}};");
|
EmitConstructor(tmp, structType);
|
||||||
_writer.WriteLine($"{CType.Create(structType)}_create({tmp});");
|
|
||||||
|
|
||||||
foreach (var initializer in refStructInitializerNode.Initializers)
|
foreach (var initializer in refStructInitializerNode.Initializers)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(initializer.Value);
|
var value = EmitExpression(initializer.Value);
|
||||||
_writer.WriteLine($"{tmp}->{initializer.Key} = {value};");
|
_writer.WriteLine($"{tmp}->{initializer.Key} = {value};");
|
||||||
|
if (initializer.Value.Type is NubRefType)
|
||||||
|
{
|
||||||
|
_writer.WriteLine($"rc_retain({tmp}->{initializer.Key});");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmp;
|
return tmp;
|
||||||
@@ -582,7 +630,7 @@ public class Generator
|
|||||||
|
|
||||||
var tmp = NewTmp();
|
var tmp = NewTmp();
|
||||||
_writer.WriteLine($"{CType.Create(structType)} {tmp} = ({CType.Create(structType)}){{0}};");
|
_writer.WriteLine($"{CType.Create(structType)} {tmp} = ({CType.Create(structType)}){{0}};");
|
||||||
_writer.WriteLine($"{CType.Create(structType)}_create(&{tmp});");
|
EmitConstructor($"&{tmp}", structType);
|
||||||
|
|
||||||
foreach (var initializer in structInitializerNode.Initializers)
|
foreach (var initializer in structInitializerNode.Initializers)
|
||||||
{
|
{
|
||||||
@@ -650,16 +698,82 @@ public class Generator
|
|||||||
foreach (var statementNode in blockNode.Statements)
|
foreach (var statementNode in blockNode.Statements)
|
||||||
{
|
{
|
||||||
EmitStatement(statementNode);
|
EmitStatement(statementNode);
|
||||||
|
|
||||||
|
if (statementNode != blockNode.Statements.Last())
|
||||||
|
{
|
||||||
|
_writer.WriteLine();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitScopeCleanup()
|
private void EmitScopeCleanup()
|
||||||
{
|
{
|
||||||
|
if (Scope.IsTerminated())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scope.Terminate();
|
||||||
|
|
||||||
|
|
||||||
var deferredStack = Scope.GetDeferred();
|
var deferredStack = Scope.GetDeferred();
|
||||||
while (deferredStack.TryPop(out var deferred))
|
while (deferredStack.TryPop(out var deferred))
|
||||||
{
|
{
|
||||||
deferred.Invoke();
|
deferred.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var variables = Scope.GetVariables();
|
||||||
|
while (variables.TryPop(out var variable))
|
||||||
|
{
|
||||||
|
EmitDestructor(variable.Ident, variable.Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EmitConstructor(string target, NubType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NubStructType structType:
|
||||||
|
{
|
||||||
|
_writer.WriteLine($"{CType.Create(structType)}_create({target});");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NubRefType:
|
||||||
|
{
|
||||||
|
_writer.WriteLine($"rc_retain({target});");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EmitDestructor(string target, NubType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case NubStructType structType:
|
||||||
|
{
|
||||||
|
_writer.WriteLine($"{CType.Create(structType)}_destroy({target});");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NubConstArrayType constArrayType:
|
||||||
|
{
|
||||||
|
var index = NewTmp();
|
||||||
|
_writer.WriteLine($"for (unsigned long long {index} = 0; {index} < {constArrayType.Size}; ++{index})");
|
||||||
|
_writer.WriteLine("{");
|
||||||
|
using (_writer.Indent())
|
||||||
|
{
|
||||||
|
EmitDestructor($"&({target}[{index}])", constArrayType.ElementType);
|
||||||
|
}
|
||||||
|
|
||||||
|
_writer.WriteLine("}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case NubRefType:
|
||||||
|
{
|
||||||
|
_writer.WriteLine($"rc_release({target});");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScopeDisposer BeginScope()
|
private ScopeDisposer BeginScope()
|
||||||
@@ -678,9 +792,24 @@ public class Generator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Variable(string ident, NubType type)
|
||||||
|
{
|
||||||
|
public string Ident { get; } = ident;
|
||||||
|
public NubType Type { get; } = type;
|
||||||
|
}
|
||||||
|
|
||||||
public class Scope
|
public class Scope
|
||||||
{
|
{
|
||||||
|
private bool _hasTerminated = false;
|
||||||
private readonly List<Action> _deferred = [];
|
private readonly List<Action> _deferred = [];
|
||||||
|
private readonly List<Variable> _variables = [];
|
||||||
|
|
||||||
|
public void Terminate()
|
||||||
|
{
|
||||||
|
_hasTerminated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsTerminated() => _hasTerminated;
|
||||||
|
|
||||||
public void Defer(Action action)
|
public void Defer(Action action)
|
||||||
{
|
{
|
||||||
@@ -688,4 +817,11 @@ public class Scope
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Stack<Action> GetDeferred() => new(_deferred);
|
public Stack<Action> GetDeferred() => new(_deferred);
|
||||||
|
|
||||||
|
public void AddVariable(string ident, NubType type)
|
||||||
|
{
|
||||||
|
_variables.Add(new Variable(ident, type));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stack<Variable> GetVariables() => new(_variables);
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
using NubLang.Ast;
|
|
||||||
using NubLang.Syntax;
|
using NubLang.Syntax;
|
||||||
|
|
||||||
namespace NubLang.Generation;
|
namespace NubLang.Generation;
|
||||||
@@ -14,6 +13,11 @@ public static class HeaderGenerator
|
|||||||
{
|
{
|
||||||
var writer = new IndentedTextWriter();
|
var writer = new IndentedTextWriter();
|
||||||
|
|
||||||
|
foreach (var import in module.Imports)
|
||||||
|
{
|
||||||
|
writer.WriteLine($"#include \"{import}.h\"");
|
||||||
|
}
|
||||||
|
|
||||||
writer.WriteLine();
|
writer.WriteLine();
|
||||||
|
|
||||||
foreach (var structType in module.StructTypes)
|
foreach (var structType in module.StructTypes)
|
||||||
|
|||||||
@@ -48,4 +48,13 @@ public sealed class Module
|
|||||||
.Where(x => x.Exported || includePrivate)
|
.Where(x => x.Exported || includePrivate)
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<string> Imports()
|
||||||
|
{
|
||||||
|
return _definitions
|
||||||
|
.OfType<ImportSyntax>()
|
||||||
|
.Select(x => x.NameToken.Value)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -36,15 +36,17 @@ public sealed class TypedModule
|
|||||||
structTypes.Add(new NubStructType(name, structSyntax.NameToken.Value, fields));
|
structTypes.Add(new NubStructType(name, structSyntax.NameToken.Value, fields));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TypedModule(functionPrototypes, structTypes);
|
return new TypedModule(functionPrototypes, structTypes, module.Imports());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TypedModule(List<FuncPrototypeNode> functionPrototypes, List<NubStructType> structTypes)
|
public TypedModule(List<FuncPrototypeNode> functionPrototypes, List<NubStructType> structTypes, List<string> imports)
|
||||||
{
|
{
|
||||||
FunctionPrototypes = functionPrototypes;
|
FunctionPrototypes = functionPrototypes;
|
||||||
StructTypes = structTypes;
|
StructTypes = structTypes;
|
||||||
|
Imports = imports;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FuncPrototypeNode> FunctionPrototypes { get; set; }
|
public List<FuncPrototypeNode> FunctionPrototypes { get; }
|
||||||
public List<NubStructType> StructTypes { get; set; }
|
public List<NubStructType> StructTypes { get; }
|
||||||
|
public List<string> Imports { get; }
|
||||||
}
|
}
|
||||||
@@ -16,25 +16,7 @@ struct Human
|
|||||||
|
|
||||||
extern "main" func main(argc: i64, argv: [?]^i8): i64
|
extern "main" func main(argc: i64, argv: [?]^i8): i64
|
||||||
{
|
{
|
||||||
let x: &Human = {
|
let x: [2]Human = [{}, {}]
|
||||||
age = 23
|
|
||||||
name = {
|
|
||||||
first = "oliver"
|
|
||||||
last = "stene"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let z: Human = {
|
|
||||||
age = 23
|
|
||||||
name = {
|
|
||||||
first = "oliver"
|
|
||||||
last = "stene"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test(x)
|
|
||||||
|
|
||||||
let y = x
|
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ void *rc_alloc(size_t size, void (*destructor)(void *self))
|
|||||||
{
|
{
|
||||||
printf("rc_alloc %zu bytes\n", size);
|
printf("rc_alloc %zu bytes\n", size);
|
||||||
ref_header *header = malloc(sizeof(ref_header) + size);
|
ref_header *header = malloc(sizeof(ref_header) + size);
|
||||||
|
memset(header, 0, size);
|
||||||
if (!header)
|
if (!header)
|
||||||
{
|
{
|
||||||
exit(69);
|
exit(69);
|
||||||
@@ -20,6 +21,9 @@ void *rc_alloc(size_t size, void (*destructor)(void *self))
|
|||||||
|
|
||||||
void rc_retain(void *obj)
|
void rc_retain(void *obj)
|
||||||
{
|
{
|
||||||
|
if (!obj)
|
||||||
|
return;
|
||||||
|
|
||||||
printf("rc_retain\n");
|
printf("rc_retain\n");
|
||||||
ref_header *header = ((ref_header *)obj) - 1;
|
ref_header *header = ((ref_header *)obj) - 1;
|
||||||
header->ref_count++;
|
header->ref_count++;
|
||||||
@@ -27,6 +31,9 @@ void rc_retain(void *obj)
|
|||||||
|
|
||||||
void rc_release(void *obj)
|
void rc_release(void *obj)
|
||||||
{
|
{
|
||||||
|
if (!obj)
|
||||||
|
return;
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
Reference in New Issue
Block a user