Add anonymous structs

This commit is contained in:
nub31
2026-02-25 21:21:28 +01:00
parent d771396bd4
commit cb4aeb9c01
6 changed files with 153 additions and 18 deletions

View File

@@ -448,6 +448,7 @@ public class Generator
NubTypeVoid => "void" + (varName != null ? $" {varName}" : ""),
NubTypeBool => "bool" + (varName != null ? $" {varName}" : ""),
NubTypeStruct type => $"struct {NameMangler.Mangle(type.Module, type.Name, type)}" + (varName != null ? $" {varName}" : ""),
NubTypeAnonymousStruct type => CTypeAnonymousStruct(type, varName),
NubTypeEnum type => $"struct {NameMangler.Mangle(type.Module, type.Name, type)}" + (varName != null ? $" {varName}" : ""),
NubTypeEnumVariant type => CType(type.EnumType, varName),
NubTypeSInt type => $"int{type.Width}_t" + (varName != null ? $" {varName}" : ""),
@@ -458,6 +459,11 @@ public class Generator
_ => throw new ArgumentOutOfRangeException(nameof(node), node, null)
};
}
private string CTypeAnonymousStruct(NubTypeAnonymousStruct type, string? varName)
{
return $"struct {{ {string.Join(' ', type.Fields.Select(x => $"{CType(x.Type)} {x.Name};"))} }}{(varName != null ? $" {varName}" : "")}";
}
}
internal class IndentedTextWriter

View File

@@ -192,6 +192,7 @@ public class ModuleGraph
{
NodeTypeBool => NubTypeBool.Instance,
NodeTypeNamed type => ResolveNamedType(type, currentModule),
NodeTypeAnonymousStruct type => NubTypeAnonymousStruct.Get(type.Fields.Select(x => new NubTypeAnonymousStruct.Field(x.Name.Ident, ResolveType(x.Type, currentModule))).ToList()),
NodeTypeFunc type => NubTypeFunc.Get(type.Parameters.Select(x => ResolveType(x, currentModule)).ToList(), ResolveType(type.ReturnType, currentModule)),
NodeTypePointer type => NubTypePointer.Get(ResolveType(type.To, currentModule)),
NodeTypeSInt type => NubTypeSInt.Get(type.Width),

View File

@@ -123,7 +123,39 @@ public class NubTypeStruct : NubType
public string Module { get; }
public string Name { get; }
public override string ToString() => $"struct {Module}::{Name}";
public override string ToString() => $"{Module}::{Name}";
}
public class NubTypeAnonymousStruct : NubType
{
private static readonly Dictionary<Signature, NubTypeAnonymousStruct> Cache = new();
public static NubTypeAnonymousStruct Get(List<Field> fields)
{
var sig = new Signature(fields);
if (!Cache.TryGetValue(sig, out var func))
Cache[sig] = func = new NubTypeAnonymousStruct(fields);
return func;
}
private NubTypeAnonymousStruct(IReadOnlyList<Field> fields)
{
Fields = fields;
}
public IReadOnlyList<Field> Fields { get; }
public override string ToString() => $"{{ {string.Join(", ", Fields.Select(x => $"{x.Name}: {x.Type}"))} }}";
public class Field(string name, NubType type)
{
public string Name { get; } = name;
public NubType Type { get; } = type;
}
private record Signature(IReadOnlyList<Field> Fields);
}
public class NubTypeEnum : NubType
@@ -147,7 +179,7 @@ public class NubTypeEnum : NubType
public string Module { get; }
public string Name { get; }
public override string ToString() => $"enum {Module}::{Name}";
public override string ToString() => $"{Module}::{Name}";
}
public class NubTypeEnumVariant : NubType
@@ -277,7 +309,7 @@ public class TypeEncoder
break;
case NubTypeStruct st:
sb.Append("T(");
sb.Append("TN(");
sb.Append(st.Module);
sb.Append(':');
sb.Append(st.Name);
@@ -312,6 +344,17 @@ public class TypeEncoder
sb.Append(')');
break;
case NubTypeAnonymousStruct s:
sb.Append("TA(");
foreach (var field in s.Fields)
{
sb.Append(field.Name);
sb.Append(':');
EncodeType(sb, field.Type);
}
sb.Append(')');
break;
default:
throw new NotSupportedException(type.GetType().Name);
}
@@ -394,23 +437,53 @@ public class TypeDecoder
return NubTypeFunc.Get(types.Take(types.Count - 1).ToList(), types.Last());
}
private NubTypeStruct DecodeStruct()
private NubType DecodeStruct()
{
var sb = new StringBuilder();
Expect('(');
while (!TryExpect(':'))
sb.Append(Consume());
if (TryExpect('A'))
{
var sb = new StringBuilder();
var fields = new List<NubTypeAnonymousStruct.Field>();
var module = sb.ToString();
sb.Clear();
Expect('(');
while (!TryExpect(')'))
{
while (!TryExpect(':'))
{
sb.Append(Consume());
}
while (!TryExpect(')'))
sb.Append(Consume());
var name = sb.ToString();
sb.Clear();
var name = sb.ToString();
var type = DecodeType();
return NubTypeStruct.Get(module, name);
fields.Add(new NubTypeAnonymousStruct.Field(name, type));
}
return NubTypeAnonymousStruct.Get(fields);
}
if (TryExpect('N'))
{
var sb = new StringBuilder();
Expect('(');
while (!TryExpect(':'))
sb.Append(Consume());
var module = sb.ToString();
sb.Clear();
while (!TryExpect(')'))
sb.Append(Consume());
var name = sb.ToString();
return NubTypeStruct.Get(module, name);
}
throw new Exception("Expected 'A' or 'N'");
}
private NubType DecodeEnum()

View File

@@ -457,6 +457,21 @@ public class Parser
return new NodeTypeFunc(TokensFrom(startIndex), parameters, returnType);
}
if (TryExpectSymbol(Symbol.OpenCurly))
{
var fields = new List<NodeTypeAnonymousStruct.Field>();
while (!TryExpectSymbol(Symbol.CloseCurly))
{
var name = ExpectIdent();
ExpectSymbol(Symbol.Colon);
var type = ParseType();
fields.Add(new NodeTypeAnonymousStruct.Field(name, type));
}
return new NodeTypeAnonymousStruct(TokensFrom(startIndex), fields);
}
if (TryExpectIdent(out var ident))
{
switch (ident.Ident)
@@ -953,6 +968,17 @@ public class NodeTypeNamed(List<Token> tokens, List<TokenIdent> sections) : Node
public List<TokenIdent> Sections { get; } = sections;
}
public class NodeTypeAnonymousStruct(List<Token> tokens, List<NodeTypeAnonymousStruct.Field> fields) : NodeType(tokens)
{
public List<Field> Fields { get; } = fields;
public class Field(TokenIdent name, NodeType type)
{
public TokenIdent Name { get; } = name;
public NodeType Type { get; } = type;
}
}
public class NodeTypePointer(List<Token> tokens, NodeType to) : NodeType(tokens)
{
public NodeType To { get; } = to;

View File

@@ -459,6 +459,7 @@ public class TypeChecker
{
NodeTypeBool => NubTypeBool.Instance,
NodeTypeNamed type => ResolveNamedType(type),
NodeTypeAnonymousStruct type => NubTypeAnonymousStruct.Get(type.Fields.Select(x => new NubTypeAnonymousStruct.Field(x.Name.Ident, ResolveType(x.Type))).ToList()),
NodeTypeFunc type => NubTypeFunc.Get(type.Parameters.Select(ResolveType).ToList(), ResolveType(type.ReturnType)),
NodeTypePointer type => NubTypePointer.Get(ResolveType(type.To)),
NodeTypeSInt type => NubTypeSInt.Get(type.Width),

View File

@@ -1,9 +1,37 @@
module math
struct vec2 { x: i32 y: i32 }
struct vec3 { x: i32 y: i32 z: i32 }
struct color { r: i32 g: i32 b: i32 a: i32 }
struct example { a: vec2 b: vec3 c: color }
struct vec2 {
x: i32
y: i32
}
struct vec3 {
x: i32
y: i32
z: i32
}
struct color {
r: i32
g: i32
b: i32
a: i32
}
struct example {
a: {
a: i32
}
b: {
b: {
c: i32
}
c: {
d: i32
}
}
}
export enum message {
quit