WIP: dev #1
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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,7 +437,34 @@ public class TypeDecoder
|
||||
return NubTypeFunc.Get(types.Take(types.Count - 1).ToList(), types.Last());
|
||||
}
|
||||
|
||||
private NubTypeStruct DecodeStruct()
|
||||
private NubType DecodeStruct()
|
||||
{
|
||||
|
||||
if (TryExpect('A'))
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
var fields = new List<NubTypeAnonymousStruct.Field>();
|
||||
|
||||
Expect('(');
|
||||
while (!TryExpect(')'))
|
||||
{
|
||||
while (!TryExpect(':'))
|
||||
{
|
||||
sb.Append(Consume());
|
||||
}
|
||||
|
||||
var name = sb.ToString();
|
||||
sb.Clear();
|
||||
|
||||
var type = DecodeType();
|
||||
|
||||
fields.Add(new NubTypeAnonymousStruct.Field(name, type));
|
||||
}
|
||||
|
||||
return NubTypeAnonymousStruct.Get(fields);
|
||||
}
|
||||
|
||||
if (TryExpect('N'))
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
@@ -413,6 +483,9 @@ public class TypeDecoder
|
||||
return NubTypeStruct.Get(module, name);
|
||||
}
|
||||
|
||||
throw new Exception("Expected 'A' or 'N'");
|
||||
}
|
||||
|
||||
private NubType DecodeEnum()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user