WIP: dev #1
@@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user