libs working

This commit is contained in:
nub31
2026-02-10 22:43:03 +01:00
parent 576abe1240
commit 9d8d8f255a
13 changed files with 234 additions and 30 deletions

View File

@@ -1,3 +1,4 @@
using System.Net;
using System.Text;
namespace Compiler;
@@ -5,7 +6,6 @@ namespace Compiler;
public abstract class NubType
{
public abstract override string ToString();
public string GetSignature() => TypeMangler.Encode(this);
}
public sealed class NubTypeVoid : NubType
@@ -193,15 +193,11 @@ static class TypeMangler
break;
case NubTypeUInt u:
sb.Append("U(");
sb.Append(u.Width);
sb.Append(')');
sb.Append("U(").Append(u.Width).Append(')');
break;
case NubTypeSInt s:
sb.Append("U(");
sb.Append(s.Width);
sb.Append(')');
sb.Append("I(").Append(s.Width).Append(')');
break;
case NubTypeString:
@@ -215,17 +211,29 @@ static class TypeMangler
break;
case NubTypeStruct st:
sb.Append($"T({st.Module}::{st.Name})");
sb.Append("T(");
sb.Append(st.Module).Append("::").Append(st.Name);
sb.Append(',').Append(st.Packed ? '1' : '0');
sb.Append('{');
for (int i = 0; i < st.Fields.Count; i++)
{
var field = st.Fields[i];
sb.Append(field.Name).Append(':');
Encode(field.Type, sb);
if (i < st.Fields.Count - 1)
sb.Append(',');
}
sb.Append("})");
break;
case NubTypeFunc fn:
sb.Append("F(");
for (int i = 0; i < fn.Parameters.Count; i++)
foreach (var parameter in fn.Parameters)
{
Encode(fn.Parameters[i], sb);
sb.Append(Encode(parameter));
sb.Append(',');
}
Encode(fn.ReturnType, sb);
sb.Append(Encode(fn.ReturnType));
sb.Append(')');
break;
@@ -233,6 +241,155 @@ static class TypeMangler
throw new NotSupportedException(type.GetType().Name);
}
}
public static NubType Decode(string encoded)
{
int pos = 0;
return Parse(encoded, ref pos);
}
private static NubType Parse(string s, ref int pos)
{
if (pos >= s.Length)
throw new InvalidOperationException("Unexpected end of string");
char c = s[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),
_ => throw new NotSupportedException($"Unknown type code '{c}' at position {pos - 1}")
};
}
private static NubTypeUInt ParseUInt(string s, ref int pos)
{
ExpectChar(s, ref pos, '(');
int width = ReadNumber(s, ref pos);
ExpectChar(s, ref pos, ')');
return NubTypeUInt.Get(width);
}
private static NubTypeSInt ParseSInt(string s, ref int pos)
{
ExpectChar(s, ref pos, '(');
int width = ReadNumber(s, ref pos);
ExpectChar(s, ref pos, ')');
return NubTypeSInt.Get(width);
}
private static NubTypePointer ParsePointer(string s, ref int pos)
{
ExpectChar(s, ref pos, '(');
var to = Parse(s, ref pos);
ExpectChar(s, ref pos, ')');
return NubTypePointer.Get(to);
}
private static NubTypeStruct ParseStruct(string s, ref int pos)
{
ExpectChar(s, ref pos, '(');
int start = pos;
while (pos < s.Length && s[pos] != ',' && s[pos] != '{') pos++;
var fullName = s[start..pos];
var parts = fullName.Split("::");
if (parts.Length != 2)
throw new InvalidOperationException($"Invalid struct name: {fullName}");
string module = parts[0], name = parts[1];
bool packed = false;
if (s[pos] == ',')
{
pos += 1;
packed = s[pos += 1] == '1';
}
var st = new NubTypeStruct(module, name, packed);
ExpectChar(s, ref pos, '{');
var fields = new List<NubTypeStruct.Field>();
while (s[pos] != '}')
{
int nameStart = pos;
while (s[pos] != ':') pos += 1;
string fieldName = s[nameStart..pos];
pos += 1;
var fieldType = Parse(s, ref pos);
fields.Add(new NubTypeStruct.Field(fieldName, fieldType));
if (s[pos] == ',') pos += 1;
}
ExpectChar(s, ref pos, '}');
ExpectChar(s, ref pos, ')');
st.ResolveFields(fields);
return st;
}
private static NubTypeFunc ParseFunc(string s, ref int pos)
{
ExpectChar(s, ref pos, '(');
var parameters = new List<NubType>();
while (true)
{
if (s[pos] == ')')
{
pos++;
break;
}
var param = Parse(s, ref pos);
parameters.Add(param);
if (s[pos] == ',')
{
pos += 1;
}
else if (s[pos] == ')')
{
pos += 1;
break;
}
else
{
throw new InvalidOperationException($"Unexpected char '{s[pos]}' in function type at {pos}");
}
}
if (parameters.Count == 0)
throw new InvalidOperationException("Function must have a return type");
var returnType = parameters[^1];
var paramTypes = parameters.Take(parameters.Count - 1).ToList();
return NubTypeFunc.Get(paramTypes, returnType);
}
private static void ExpectChar(string s, ref int pos, char expected)
{
if (pos >= s.Length || s[pos] != expected)
throw new InvalidOperationException($"Expected '{expected}' at position {pos}");
pos += 1;
}
private static int ReadNumber(string s, ref int pos)
{
int start = pos;
while (pos < s.Length && char.IsDigit(s[pos])) pos += 1;
if (start == pos) throw new InvalidOperationException($"Expected number at position {start}");
return int.Parse(s[start..pos]);
}
}
static class Hashing