WIP: dev #1

Draft
nub31 wants to merge 103 commits from dev into master
2 changed files with 196 additions and 26 deletions
Showing only changes of commit da2fa81c39 - Show all commits

View File

@@ -91,7 +91,7 @@ public class Generator
writer = new IndentedTextWriter(); writer = new IndentedTextWriter();
writer.WriteLine(""" writer.WriteLine($$"""
#include <float.h> #include <float.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
@@ -99,8 +99,6 @@ public class Generator
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#define FLAG_STRING_LITERAL 1
"""); """);
while (referencedTypes.Count != 0) while (referencedTypes.Count != 0)
@@ -132,11 +130,48 @@ public class Generator
{ {
writer.WriteLine("char *data;"); writer.WriteLine("char *data;");
writer.WriteLine("size_t length;"); writer.WriteLine("size_t length;");
writer.WriteLine("uint32_t ref;"); writer.WriteLine("int32_t ref;");
writer.WriteLine("uint32_t flags;"); writer.WriteLine("uint32_t flags;");
} }
writer.WriteLine("};"); writer.WriteLine("};");
writer.WriteLine(); writer.WriteLine();
writer.WriteLine("#define FLAG_STRING_LITERAL 1");
writer.WriteLine();
writer.WriteLine($"static inline void rc_inc({CType(NubTypeString.Instance, "string")})");
writer.WriteLine("{");
using (writer.Indent())
{
writer.WriteLine($"string->ref += 1;");
}
writer.WriteLine("}");
writer.WriteLine();
writer.WriteLine($"static inline void rc_dec({CType(NubTypeString.Instance, "string")})");
writer.WriteLine("{");
using (writer.Indent())
{
writer.WriteLine($"string->ref -= 1;");
writer.WriteLine($"if (string->ref <= 0)");
writer.WriteLine("{");
using (writer.Indent())
{
writer.WriteLine($"if ((string->flags & FLAG_STRING_LITERAL) == 0)");
writer.WriteLine("{");
using (writer.Indent())
{
writer.WriteLine($"free(string->data);");
}
writer.WriteLine("}");
writer.WriteLine($"free(string);");
}
writer.WriteLine("}");
}
writer.WriteLine("}");
writer.WriteLine();
break; break;
} }
case NubTypeStruct structType: case NubTypeStruct structType:
@@ -302,7 +337,7 @@ public class Generator
var value = EmitExpression(statement.Value); var value = EmitExpression(statement.Value);
EmitCopyConstructor(value, statement.Value.Type); EmitCopyConstructor(value, statement.Value.Type);
writer.WriteLine($"{CType(statement.Type, statement.Name.Ident)} = {value};"); writer.WriteLine($"{CType(statement.Type, statement.Name.Ident)} = {value};");
scopes.Peek().Locals.Add((statement.Name.Ident, statement.Type)); scopes.Peek().DeconstructableNames.Add((statement.Name.Ident, statement.Type));
} }
private void EmitStatementAssignment(TypedNodeStatementAssignment statement) private void EmitStatementAssignment(TypedNodeStatementAssignment statement)
@@ -397,7 +432,7 @@ public class Generator
private string EmitExpression(TypedNodeExpression node) private string EmitExpression(TypedNodeExpression node)
{ {
return node switch var value = node switch
{ {
TypedNodeExpressionBinary expression => EmitExpressionBinary(expression), TypedNodeExpressionBinary expression => EmitExpressionBinary(expression),
TypedNodeExpressionUnary expression => EmitExpressionUnary(expression), TypedNodeExpressionUnary expression => EmitExpressionUnary(expression),
@@ -414,6 +449,10 @@ public class Generator
TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression), TypedNodeExpressionFuncCall expression => EmitExpressionFuncCall(expression),
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null) _ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
}; };
var tmp = TmpName();
writer.WriteLine($"{CType(node.Type, tmp)} = {value};");
return tmp;
} }
private string EmitExpressionBinary(TypedNodeExpressionBinary expression) private string EmitExpressionBinary(TypedNodeExpressionBinary expression)
@@ -457,7 +496,7 @@ public class Generator
private string EmitExpressionStringLiteral(TypedNodeExpressionStringLiteral expression) private string EmitExpressionStringLiteral(TypedNodeExpressionStringLiteral expression)
{ {
var name = TmpName(); var name = TmpName();
scopes.Peek().Locals.Add((name, expression.Type)); scopes.Peek().DeconstructableNames.Add((name, expression.Type));
var variable = CType(expression.Type, name); var variable = CType(expression.Type, name);
@@ -472,21 +511,30 @@ public class Generator
private string EmitExpressionStructLiteral(TypedNodeExpressionStructLiteral expression) private string EmitExpressionStructLiteral(TypedNodeExpressionStructLiteral expression)
{ {
var name = TmpName();
scopes.Peek().DeconstructableNames.Add((name, expression.Type));
var initializerValues = new Dictionary<string, string>(); var initializerValues = new Dictionary<string, string>();
foreach (var initializer in expression.Initializers) foreach (var initializer in expression.Initializers)
{ {
var values = EmitExpression(initializer.Value); var value = EmitExpression(initializer.Value);
initializerValues[initializer.Name.Ident] = values; EmitCopyConstructor(value, initializer.Value.Type);
initializerValues[initializer.Name.Ident] = value;
} }
var initializerStrings = initializerValues.Select(x => $".{x.Key} = {x.Value}"); var initializerStrings = initializerValues.Select(x => $".{x.Key} = {x.Value}");
return $"({CType(expression.Type)}){{ {string.Join(", ", initializerStrings)} }}"; writer.WriteLine($"{CType(expression.Type, name)} = ({CType(expression.Type)}){{ {string.Join(", ", initializerStrings)} }};");
return name;
} }
private string EmitExpressionEnumLiteral(TypedNodeExpressionEnumLiteral expression) private string EmitExpressionEnumLiteral(TypedNodeExpressionEnumLiteral expression)
{ {
var name = TmpName();
scopes.Peek().DeconstructableNames.Add((name, expression.Type));
var enumVariantType = (NubTypeEnumVariant)expression.Type; var enumVariantType = (NubTypeEnumVariant)expression.Type;
if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, true, out var info)) if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, true, out var info))
@@ -496,8 +544,11 @@ public class Generator
var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == enumVariantType.Variant); var tag = enumInfo.Variants.ToList().FindIndex(x => x.Name == enumVariantType.Variant);
var value = EmitExpression(expression.Value); var value = EmitExpression(expression.Value);
EmitCopyConstructor(value, expression.Value.Type);
return $"({CType(expression.Type)}){{ .tag = {tag}, .{enumVariantType.Variant} = {value} }}"; writer.WriteLine($"{CType(expression.Type, name)} = ({CType(expression.Type)}){{ .tag = {tag}, .{enumVariantType.Variant} = {value} }};");
return name;
} }
private string EmitExpressionMemberAccess(TypedNodeExpressionStructMemberAccess expression) private string EmitExpressionMemberAccess(TypedNodeExpressionStructMemberAccess expression)
@@ -568,9 +619,9 @@ public class Generator
{ {
foreach (var scope in scopes.Reverse()) foreach (var scope in scopes.Reverse())
{ {
for (int i = scope.Locals.Count - 1; i >= 0; i--) for (int i = scope.DeconstructableNames.Count - 1; i >= 0; i--)
{ {
var (name, type) = scope.Locals[i]; var (name, type) = scope.DeconstructableNames[i];
EmitCopyDestructor(name, type); EmitCopyDestructor(name, type);
} }
} }
@@ -578,9 +629,9 @@ public class Generator
private void EmitCleanupCurrentScope(Scope scope) private void EmitCleanupCurrentScope(Scope scope)
{ {
for (int i = scope.Locals.Count - 1; i >= 0; i--) for (int i = scope.DeconstructableNames.Count - 1; i >= 0; i--)
{ {
var (name, type) = scope.Locals[i]; var (name, type) = scope.DeconstructableNames[i];
EmitCopyDestructor(name, type); EmitCopyDestructor(name, type);
} }
} }
@@ -590,8 +641,65 @@ public class Generator
switch (type) switch (type)
{ {
case NubTypeString: case NubTypeString:
writer.WriteLine($"{value}->ref += 1;"); {
writer.WriteLine($"rc_inc({value});");
break; break;
}
case NubTypeStruct structType:
{
if (!moduleGraph.TryResolveType(structType.Module, structType.Name, true, out var info) || info is not Module.TypeInfoStruct structInfo)
throw new UnreachableException();
foreach (var field in structInfo.Fields)
{
EmitCopyConstructor($"{value}.{field.Name}", field.Type);
}
break;
}
case NubTypeAnonymousStruct anonymousStructType:
{
foreach (var field in anonymousStructType.Fields)
{
EmitCopyConstructor($"{value}.{field.Name}", field.Type);
}
break;
}
case NubTypeEnum enumType:
{
if (!moduleGraph.TryResolveType(enumType.Module, enumType.Name, true, out var info) || info is not Module.TypeInfoEnum enumInfo)
throw new UnreachableException();
writer.WriteLine($"switch ({value}.tag)");
writer.WriteLine("{");
using (writer.Indent())
{
for (int i = 0; i < enumInfo.Variants.Count; i++)
{
Module.TypeInfoEnum.Variant variant = enumInfo.Variants[i];
writer.WriteLine($"case {i}:");
writer.WriteLine("{");
using (writer.Indent())
{
EmitCopyConstructor($"{value}.{variant.Name}", variant.Type);
writer.WriteLine("break;");
}
writer.WriteLine("}");
}
}
writer.WriteLine("}");
break;
}
case NubTypeEnumVariant enumVariantType:
{
if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, true, out var info) || info is not Module.TypeInfoEnum enumInfo)
throw new UnreachableException();
var variant = enumInfo.Variants.First(x => x.Name == enumVariantType.Variant);
EmitCopyConstructor($"{value}.{variant.Name}", variant.Type);
break;
}
} }
} }
@@ -600,22 +708,65 @@ public class Generator
switch (type) switch (type)
{ {
case NubTypeString: case NubTypeString:
writer.WriteLine($"{value}->ref -= 1;"); {
writer.WriteLine($"if ({value}->ref == 0)"); writer.WriteLine($"rc_dec({value});");
break;
}
case NubTypeStruct structType:
{
if (!moduleGraph.TryResolveType(structType.Module, structType.Name, true, out var info) || info is not Module.TypeInfoStruct structInfo)
throw new UnreachableException();
foreach (var field in structInfo.Fields)
{
EmitCopyDestructor($"{value}.{field.Name}", field.Type);
}
break;
}
case NubTypeAnonymousStruct anonymousStructType:
{
foreach (var field in anonymousStructType.Fields)
{
EmitCopyDestructor($"{value}.{field.Name}", field.Type);
}
break;
}
case NubTypeEnum enumType:
{
if (!moduleGraph.TryResolveType(enumType.Module, enumType.Name, true, out var info) || info is not Module.TypeInfoEnum enumInfo)
throw new UnreachableException();
writer.WriteLine($"switch ({value}.tag)");
writer.WriteLine("{"); writer.WriteLine("{");
using (writer.Indent()) using (writer.Indent())
{ {
writer.WriteLine($"if (({value}->flags & FLAG_STRING_LITERAL) == 0)"); for (int i = 0; i < enumInfo.Variants.Count; i++)
writer.WriteLine("{");
using (writer.Indent())
{ {
writer.WriteLine($"free({value}->data);"); var variant = enumInfo.Variants[i];
writer.WriteLine($"case {i}:");
writer.WriteLine("{");
using (writer.Indent())
{
EmitCopyDestructor($"{value}.{variant.Name}", variant.Type);
writer.WriteLine("break;");
}
writer.WriteLine("}");
} }
writer.WriteLine("}");
writer.WriteLine($"free({value});");
} }
writer.WriteLine("}"); writer.WriteLine("}");
break; break;
}
case NubTypeEnumVariant enumVariantType:
{
if (!moduleGraph.TryResolveType(enumVariantType.EnumType.Module, enumVariantType.EnumType.Name, true, out var info) || info is not Module.TypeInfoEnum enumInfo)
throw new UnreachableException();
var variant = enumInfo.Variants.First(x => x.Name == enumVariantType.Variant);
EmitCopyDestructor($"{value}.{variant.Name}", variant.Type);
break;
}
} }
} }
@@ -633,7 +784,7 @@ public class Generator
private class Scope private class Scope
{ {
public List<(string Name, NubType Type)> Locals { get; } = []; public List<(string Name, NubType Type)> DeconstructableNames { get; } = [];
public bool Unreachable { get; set; } public bool Unreachable { get; set; }
} }
} }

View File

@@ -1,6 +1,25 @@
module main module main
extern func puts(text: ^u8)
export func print(text: string) {
puts(text.ptr)
}
enum Message {
Tell: string
}
func main(): i32 { func main(): i32 {
core::print("Your mom") let x = "test"
let y = {
abc = x
}
let a: Message = enum Message::Tell x
core::print(x)
return 0 return 0
} }