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

@@ -23,8 +23,6 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
return new Manifest(1, GetModules().Select(x => x.CreateManifestModule()).ToList()); return new Manifest(1, GetModules().Select(x => x.CreateManifestModule()).ToList());
} }
public record Manifest(int Version, IReadOnlyList<Module.ManifestModule> Modules);
public sealed class Module(string name) public sealed class Module(string name)
{ {
public string Name { get; } = name; public string Name { get; } = name;
@@ -110,7 +108,7 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
public ManifestCustomTypeInfo CreateManifestCustomTypeInfo() public ManifestCustomTypeInfo CreateManifestCustomTypeInfo()
{ {
return new ManifestCustomTypeInfo(Type, Exported); return new ManifestCustomTypeInfo(TypeMangler.Encode(Type), Exported);
} }
} }
@@ -122,13 +120,9 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
public ManifestIdentifierInfo CreateManifestIdentifierInfo() public ManifestIdentifierInfo CreateManifestIdentifierInfo()
{ {
return new ManifestIdentifierInfo(Type, Exported); return new ManifestIdentifierInfo(TypeMangler.Encode(Type), Exported);
} }
} }
public record ManifestModule(string Name, Dictionary<string, ManifestCustomTypeInfo> CustomTypes, Dictionary<string, ManifestIdentifierInfo> Identifiers);
public record ManifestCustomTypeInfo(NubType Type, bool Exported);
public record ManifestIdentifierInfo(NubType Type, bool Exported);
} }
public class Builder public class Builder
@@ -165,12 +159,14 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
foreach (var customType in manifestModule.CustomTypes) foreach (var customType in manifestModule.CustomTypes)
{ {
module.AddCustomType(customType.Key, new Module.CustomTypeInfo(customType.Value.Type, customType.Value.Exported, Module.Source.Lib)); var decoded = TypeMangler.Decode(customType.Value.EncodedType);
module.AddCustomType(customType.Key, new Module.CustomTypeInfo(decoded, customType.Value.Exported, Module.Source.Lib));
} }
foreach (var customType in manifestModule.Identifiers) foreach (var identifier in manifestModule.Identifiers)
{ {
module.AddIdentifier(customType.Key, new Module.IdentifierInfo(customType.Value.Type, customType.Value.Exported, Module.Source.Lib)); var decoded = TypeMangler.Decode(identifier.Value.EncodedType);
module.AddIdentifier(identifier.Key, new Module.IdentifierInfo(decoded, identifier.Value.Exported, Module.Source.Lib));
} }
} }
} }
@@ -275,3 +271,8 @@ public class ModuleGraph(Dictionary<string, ModuleGraph.Module> modules)
} }
} }
} }
public record Manifest(int Version, IReadOnlyList<ManifestModule> Modules);
public record ManifestModule(string Name, Dictionary<string, ManifestCustomTypeInfo> CustomTypes, Dictionary<string, ManifestIdentifierInfo> Identifiers);
public record ManifestCustomTypeInfo(string EncodedType, bool Exported);
public record ManifestIdentifierInfo(string EncodedType, bool Exported);

View File

@@ -1,3 +1,4 @@
using System.Net;
using System.Text; using System.Text;
namespace Compiler; namespace Compiler;
@@ -5,7 +6,6 @@ namespace Compiler;
public abstract class NubType public abstract class NubType
{ {
public abstract override string ToString(); public abstract override string ToString();
public string GetSignature() => TypeMangler.Encode(this);
} }
public sealed class NubTypeVoid : NubType public sealed class NubTypeVoid : NubType
@@ -193,15 +193,11 @@ static class TypeMangler
break; break;
case NubTypeUInt u: case NubTypeUInt u:
sb.Append("U("); sb.Append("U(").Append(u.Width).Append(')');
sb.Append(u.Width);
sb.Append(')');
break; break;
case NubTypeSInt s: case NubTypeSInt s:
sb.Append("U("); sb.Append("I(").Append(s.Width).Append(')');
sb.Append(s.Width);
sb.Append(')');
break; break;
case NubTypeString: case NubTypeString:
@@ -215,17 +211,29 @@ static class TypeMangler
break; break;
case NubTypeStruct st: 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; break;
case NubTypeFunc fn: case NubTypeFunc fn:
sb.Append("F("); 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(','); sb.Append(',');
} }
Encode(fn.ReturnType, sb); sb.Append(Encode(fn.ReturnType));
sb.Append(')'); sb.Append(')');
break; break;
@@ -233,6 +241,155 @@ static class TypeMangler
throw new NotSupportedException(type.GetType().Name); 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 static class Hashing

View File

@@ -163,7 +163,7 @@ static void CleanDirectory(string dirName)
} }
} }
static void WriteNublib(string outputPath, string archivePath, ModuleGraph.Manifest manifest) static void WriteNublib(string outputPath, string archivePath, Manifest manifest)
{ {
using var fs = new FileStream(outputPath, FileMode.Create); using var fs = new FileStream(outputPath, FileMode.Create);
using var zip = new ZipArchive(fs, ZipArchiveMode.Create); using var zip = new ZipArchive(fs, ZipArchiveMode.Create);
@@ -174,6 +174,8 @@ static void WriteNublib(string outputPath, string archivePath, ModuleGraph.Manif
WriteIndented = true, WriteIndented = true,
}); });
File.WriteAllText(".build/manifest.json", serialized);
var manifestEntry = zip.CreateEntry("manifest.json"); var manifestEntry = zip.CreateEntry("manifest.json");
using (var writer = new StreamWriter(manifestEntry.Open())) using (var writer = new StreamWriter(manifestEntry.Open()))
{ {
@@ -195,11 +197,11 @@ static NublibLoadResult ReadNublib(string nublibPath)
var manifestEntry = zip.GetEntry("manifest.json") ?? throw new FileNotFoundException("Manifest not found in nublib", "manifest.json"); var manifestEntry = zip.GetEntry("manifest.json") ?? throw new FileNotFoundException("Manifest not found in nublib", "manifest.json");
ModuleGraph.Manifest manifest; Manifest manifest;
using (var reader = new StreamReader(manifestEntry.Open())) using (var reader = new StreamReader(manifestEntry.Open()))
{ {
var json = reader.ReadToEnd(); var json = reader.ReadToEnd();
manifest = JsonSerializer.Deserialize<ModuleGraph.Manifest>(json) ?? throw new InvalidDataException("Failed to deserialize manifest.json"); manifest = JsonSerializer.Deserialize<Manifest>(json) ?? throw new InvalidDataException("Failed to deserialize manifest.json");
} }
var archiveEntry = zip.Entries.FirstOrDefault(e => e.Name.EndsWith(".a")) ?? throw new FileNotFoundException("Archive not found in nublib", "*.a"); var archiveEntry = zip.Entries.FirstOrDefault(e => e.Name.EndsWith(".a")) ?? throw new FileNotFoundException("Archive not found in nublib", "*.a");
@@ -214,4 +216,4 @@ static NublibLoadResult ReadNublib(string nublibPath)
return new NublibLoadResult(manifest, tempArchivePath); return new NublibLoadResult(manifest, tempArchivePath);
} }
public record NublibLoadResult(ModuleGraph.Manifest Manifest, string ArchivePath); public record NublibLoadResult(Manifest Manifest, string ArchivePath);

View File

@@ -0,0 +1,15 @@
{
"version": 1,
"modules": [
{
"name": "math",
"customTypes": {},
"identifiers": {
"add": {
"encodedType": "F(I(32),I(32),I(32))",
"exported": true
}
}
}
]
}

Binary file not shown.

View File

@@ -12,10 +12,10 @@ struct nub_core_string
int32_t nub_math_add_cc3fc9d68812b10d(int32_t, int32_t); int32_t nub_math_add_500748c2c6d70959(int32_t, int32_t);
int32_t nub_math_add_cc3fc9d68812b10d(int32_t a, int32_t b) int32_t nub_math_add_500748c2c6d70959(int32_t a, int32_t b)
{ {
{ {
return (a + b); return (a + b);

Binary file not shown.

Binary file not shown.

BIN
examples/program/.build/out Executable file

Binary file not shown.

View File

@@ -0,0 +1,29 @@
#include <float.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
struct nub_core_string
{
const char *data;
int length;
};
extern int32_t nub_math_add_500748c2c6d70959(int32_t, int32_t);
int32_t nub_main_main_55882df37f903935();
int main(int argc, char *argv[])
{
return nub_main_main_55882df37f903935();
}
int32_t nub_main_main_55882df37f903935()
{
{
return nub_math_add_500748c2c6d70959(1, 2);
}
}

View File

@@ -2,5 +2,5 @@ module main
func main(): i32 func main(): i32
{ {
return math::add(1, 2) return math::add(1 2)
} }