...
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Compiler;
|
||||
@@ -8,7 +7,7 @@ public abstract class NubType
|
||||
public abstract override string ToString();
|
||||
}
|
||||
|
||||
public sealed class NubTypeVoid : NubType
|
||||
public class NubTypeVoid : NubType
|
||||
{
|
||||
public static readonly NubTypeVoid Instance = new();
|
||||
|
||||
@@ -19,7 +18,7 @@ public sealed class NubTypeVoid : NubType
|
||||
public override string ToString() => "void";
|
||||
}
|
||||
|
||||
public sealed class NubTypeUInt : NubType
|
||||
public class NubTypeUInt : NubType
|
||||
{
|
||||
private static readonly Dictionary<int, NubTypeUInt> Cache = new();
|
||||
|
||||
@@ -41,7 +40,7 @@ public sealed class NubTypeUInt : NubType
|
||||
public override string ToString() => $"u{Width}";
|
||||
}
|
||||
|
||||
public sealed class NubTypeSInt : NubType
|
||||
public class NubTypeSInt : NubType
|
||||
{
|
||||
private static readonly Dictionary<int, NubTypeSInt> Cache = new();
|
||||
|
||||
@@ -63,7 +62,7 @@ public sealed class NubTypeSInt : NubType
|
||||
public override string ToString() => $"i{Width}";
|
||||
}
|
||||
|
||||
public sealed class NubTypeBool : NubType
|
||||
public class NubTypeBool : NubType
|
||||
{
|
||||
public static readonly NubTypeBool Instance = new();
|
||||
|
||||
@@ -74,7 +73,7 @@ public sealed class NubTypeBool : NubType
|
||||
public override string ToString() => "bool";
|
||||
}
|
||||
|
||||
public sealed class NubTypeString : NubType
|
||||
public class NubTypeString : NubType
|
||||
{
|
||||
public static readonly NubTypeString Instance = new();
|
||||
|
||||
@@ -85,7 +84,7 @@ public sealed class NubTypeString : NubType
|
||||
public override string ToString() => "string";
|
||||
}
|
||||
|
||||
public sealed class NubTypeStruct : NubType
|
||||
public class NubTypeStruct : NubType
|
||||
{
|
||||
public string Name { get; }
|
||||
public string Module { get; }
|
||||
@@ -112,14 +111,14 @@ public sealed class NubTypeStruct : NubType
|
||||
|
||||
public override string ToString() => _resolvedFields == null ? $"struct {Module}::{Name} <unresolved>" : $"struct {Module}::{Name} {{ {string.Join(' ', Fields.Select(f => $"{f.Name}: {f.Type}"))} }}";
|
||||
|
||||
public sealed class Field(string name, NubType type)
|
||||
public class Field(string name, NubType type)
|
||||
{
|
||||
public string Name { get; } = name;
|
||||
public NubType Type { get; } = type;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class NubTypePointer : NubType
|
||||
public class NubTypePointer : NubType
|
||||
{
|
||||
private static readonly Dictionary<NubType, NubTypePointer> Cache = new();
|
||||
|
||||
@@ -141,7 +140,7 @@ public sealed class NubTypePointer : NubType
|
||||
public override string ToString() => $"^{To}";
|
||||
}
|
||||
|
||||
public sealed class NubTypeFunc : NubType
|
||||
public class NubTypeFunc : NubType
|
||||
{
|
||||
private static readonly Dictionary<Signature, NubTypeFunc> Cache = new();
|
||||
|
||||
@@ -171,7 +170,7 @@ public sealed class NubTypeFunc : NubType
|
||||
private readonly record struct Signature(IReadOnlyList<NubType> Parameters, NubType ReturnType);
|
||||
}
|
||||
|
||||
static class TypeMangler
|
||||
static class TypeEncoder
|
||||
{
|
||||
public static string Encode(NubType type)
|
||||
{
|
||||
@@ -241,63 +240,78 @@ static class TypeMangler
|
||||
throw new NotSupportedException(type.GetType().Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TypeDecoder
|
||||
{
|
||||
public static NubType Decode(string encoded)
|
||||
{
|
||||
int pos = 0;
|
||||
return Parse(encoded, ref pos);
|
||||
return new TypeDecoder(encoded).Decode();
|
||||
}
|
||||
|
||||
private static NubType Parse(string s, ref int pos)
|
||||
private TypeDecoder(string encoded)
|
||||
{
|
||||
if (pos >= s.Length)
|
||||
this.encoded = encoded;
|
||||
}
|
||||
|
||||
private readonly string encoded;
|
||||
private int pos;
|
||||
|
||||
private NubType Decode()
|
||||
{
|
||||
return Parse();
|
||||
}
|
||||
|
||||
private NubType Parse()
|
||||
{
|
||||
if (pos >= encoded.Length)
|
||||
throw new InvalidOperationException("Unexpected end of string");
|
||||
|
||||
char c = s[pos++];
|
||||
char c = encoded[pos++];
|
||||
return c switch
|
||||
{
|
||||
'V' => NubTypeVoid.Instance,
|
||||
'B' => NubTypeBool.Instance,
|
||||
'S' => NubTypeString.Instance,
|
||||
'U' => ParseUInt(s, ref pos),
|
||||
'I' => ParseSInt(s, ref pos),
|
||||
'P' => ParsePointer(s, ref pos),
|
||||
'T' => ParseStruct(s, ref pos),
|
||||
'F' => ParseFunc(s, ref pos),
|
||||
'U' => ParseUInt(),
|
||||
'I' => ParseSInt(),
|
||||
'P' => ParsePointer(),
|
||||
'T' => ParseStruct(),
|
||||
'F' => ParseFunc(),
|
||||
_ => throw new NotSupportedException($"Unknown type code '{c}' at position {pos - 1}")
|
||||
};
|
||||
}
|
||||
|
||||
private static NubTypeUInt ParseUInt(string s, ref int pos)
|
||||
private NubTypeUInt ParseUInt()
|
||||
{
|
||||
ExpectChar(s, ref pos, '(');
|
||||
int width = ReadNumber(s, ref pos);
|
||||
ExpectChar(s, ref pos, ')');
|
||||
ExpectChar('(');
|
||||
int width = ReadNumber();
|
||||
ExpectChar(')');
|
||||
return NubTypeUInt.Get(width);
|
||||
}
|
||||
|
||||
private static NubTypeSInt ParseSInt(string s, ref int pos)
|
||||
private NubTypeSInt ParseSInt()
|
||||
{
|
||||
ExpectChar(s, ref pos, '(');
|
||||
int width = ReadNumber(s, ref pos);
|
||||
ExpectChar(s, ref pos, ')');
|
||||
ExpectChar('(');
|
||||
int width = ReadNumber();
|
||||
ExpectChar(')');
|
||||
return NubTypeSInt.Get(width);
|
||||
}
|
||||
|
||||
private static NubTypePointer ParsePointer(string s, ref int pos)
|
||||
private NubTypePointer ParsePointer()
|
||||
{
|
||||
ExpectChar(s, ref pos, '(');
|
||||
var to = Parse(s, ref pos);
|
||||
ExpectChar(s, ref pos, ')');
|
||||
ExpectChar('(');
|
||||
var to = Parse();
|
||||
ExpectChar(')');
|
||||
return NubTypePointer.Get(to);
|
||||
}
|
||||
|
||||
private static NubTypeStruct ParseStruct(string s, ref int pos)
|
||||
private NubTypeStruct ParseStruct()
|
||||
{
|
||||
ExpectChar(s, ref pos, '(');
|
||||
ExpectChar('(');
|
||||
int start = pos;
|
||||
while (pos < s.Length && s[pos] != ',' && s[pos] != '{') pos++;
|
||||
var fullName = s[start..pos];
|
||||
while (pos < encoded.Length && encoded[pos] != ',' && encoded[pos] != '{') pos++;
|
||||
var fullName = encoded[start..pos];
|
||||
var parts = fullName.Split("::");
|
||||
if (parts.Length != 2)
|
||||
throw new InvalidOperationException($"Invalid struct name: {fullName}");
|
||||
@@ -305,64 +319,64 @@ static class TypeMangler
|
||||
string module = parts[0], name = parts[1];
|
||||
|
||||
bool packed = false;
|
||||
if (s[pos] == ',')
|
||||
if (encoded[pos] == ',')
|
||||
{
|
||||
pos += 1;
|
||||
packed = s[pos += 1] == '1';
|
||||
packed = encoded[pos += 1] == '1';
|
||||
}
|
||||
|
||||
var st = new NubTypeStruct(module, name, packed);
|
||||
|
||||
ExpectChar(s, ref pos, '{');
|
||||
ExpectChar('{');
|
||||
|
||||
var fields = new List<NubTypeStruct.Field>();
|
||||
while (s[pos] != '}')
|
||||
while (encoded[pos] != '}')
|
||||
{
|
||||
int nameStart = pos;
|
||||
while (s[pos] != ':') pos += 1;
|
||||
string fieldName = s[nameStart..pos];
|
||||
while (encoded[pos] != ':') pos += 1;
|
||||
string fieldName = encoded[nameStart..pos];
|
||||
pos += 1;
|
||||
|
||||
var fieldType = Parse(s, ref pos);
|
||||
var fieldType = Parse();
|
||||
fields.Add(new NubTypeStruct.Field(fieldName, fieldType));
|
||||
|
||||
if (s[pos] == ',') pos += 1;
|
||||
if (encoded[pos] == ',') pos += 1;
|
||||
}
|
||||
|
||||
ExpectChar(s, ref pos, '}');
|
||||
ExpectChar(s, ref pos, ')');
|
||||
ExpectChar('}');
|
||||
ExpectChar(')');
|
||||
|
||||
st.ResolveFields(fields);
|
||||
return st;
|
||||
}
|
||||
|
||||
private static NubTypeFunc ParseFunc(string s, ref int pos)
|
||||
private NubTypeFunc ParseFunc()
|
||||
{
|
||||
ExpectChar(s, ref pos, '(');
|
||||
ExpectChar('(');
|
||||
var parameters = new List<NubType>();
|
||||
while (true)
|
||||
{
|
||||
if (s[pos] == ')')
|
||||
if (encoded[pos] == ')')
|
||||
{
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
|
||||
var param = Parse(s, ref pos);
|
||||
var param = Parse();
|
||||
parameters.Add(param);
|
||||
|
||||
if (s[pos] == ',')
|
||||
if (encoded[pos] == ',')
|
||||
{
|
||||
pos += 1;
|
||||
}
|
||||
else if (s[pos] == ')')
|
||||
else if (encoded[pos] == ')')
|
||||
{
|
||||
pos += 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Unexpected char '{s[pos]}' in function type at {pos}");
|
||||
throw new InvalidOperationException($"Unexpected char '{encoded[pos]}' in function type at {pos}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,20 +389,20 @@ static class TypeMangler
|
||||
return NubTypeFunc.Get(paramTypes, returnType);
|
||||
}
|
||||
|
||||
private static void ExpectChar(string s, ref int pos, char expected)
|
||||
private void ExpectChar(char expected)
|
||||
{
|
||||
if (pos >= s.Length || s[pos] != expected)
|
||||
if (pos >= encoded.Length || encoded[pos] != expected)
|
||||
throw new InvalidOperationException($"Expected '{expected}' at position {pos}");
|
||||
|
||||
pos += 1;
|
||||
}
|
||||
|
||||
private static int ReadNumber(string s, ref int pos)
|
||||
private int ReadNumber()
|
||||
{
|
||||
int start = pos;
|
||||
while (pos < s.Length && char.IsDigit(s[pos])) pos += 1;
|
||||
while (pos < encoded.Length && char.IsDigit(encoded[pos])) pos += 1;
|
||||
if (start == pos) throw new InvalidOperationException($"Expected number at position {start}");
|
||||
return int.Parse(s[start..pos]);
|
||||
return int.Parse(encoded[start..pos]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +428,7 @@ static class SymbolNameGen
|
||||
{
|
||||
public static string Exported(string module, string function, NubType type)
|
||||
{
|
||||
var canonical = TypeMangler.Encode(type);
|
||||
var canonical = TypeEncoder.Encode(type);
|
||||
var hash = Hashing.Fnv1a64(canonical);
|
||||
|
||||
return $"nub_{Sanitize(module)}_{Sanitize(function)}_{hash:x16}";
|
||||
|
||||
Reference in New Issue
Block a user