From 9d8d8f255ad44e2971542b9ff62bbdf9602547c8 Mon Sep 17 00:00:00 2001 From: nub31 Date: Tue, 10 Feb 2026 22:43:03 +0100 Subject: [PATCH] libs working --- compiler/ModuleGraph.cs | 25 ++-- compiler/NubType.cs | 179 ++++++++++++++++++++++++-- compiler/Program.cs | 10 +- examples/math/.build/manifest.json | 15 +++ examples/math/.build/out.a | Bin 1390 -> 1390 bytes examples/math/.build/out.c | 4 +- examples/math/.build/out.nublib | Bin 789 -> 763 bytes examples/math/.build/out.o | Bin 1224 -> 1224 bytes examples/program/.build/out | Bin 0 -> 15360 bytes examples/program/.build/out.c | 29 +++++ examples/program/main.nub | 2 +- {compiler => examples/test}/test.nub | 0 {compiler => examples/test}/test2.nub | 0 13 files changed, 234 insertions(+), 30 deletions(-) create mode 100644 examples/math/.build/manifest.json create mode 100755 examples/program/.build/out create mode 100644 examples/program/.build/out.c rename {compiler => examples/test}/test.nub (100%) rename {compiler => examples/test}/test2.nub (100%) diff --git a/compiler/ModuleGraph.cs b/compiler/ModuleGraph.cs index cfb8837..655b9c7 100644 --- a/compiler/ModuleGraph.cs +++ b/compiler/ModuleGraph.cs @@ -23,8 +23,6 @@ public class ModuleGraph(Dictionary modules) return new Manifest(1, GetModules().Select(x => x.CreateManifestModule()).ToList()); } - public record Manifest(int Version, IReadOnlyList Modules); - public sealed class Module(string name) { public string Name { get; } = name; @@ -110,7 +108,7 @@ public class ModuleGraph(Dictionary modules) public ManifestCustomTypeInfo CreateManifestCustomTypeInfo() { - return new ManifestCustomTypeInfo(Type, Exported); + return new ManifestCustomTypeInfo(TypeMangler.Encode(Type), Exported); } } @@ -122,13 +120,9 @@ public class ModuleGraph(Dictionary modules) public ManifestIdentifierInfo CreateManifestIdentifierInfo() { - return new ManifestIdentifierInfo(Type, Exported); + return new ManifestIdentifierInfo(TypeMangler.Encode(Type), Exported); } } - - public record ManifestModule(string Name, Dictionary CustomTypes, Dictionary Identifiers); - public record ManifestCustomTypeInfo(NubType Type, bool Exported); - public record ManifestIdentifierInfo(NubType Type, bool Exported); } public class Builder @@ -165,12 +159,14 @@ public class ModuleGraph(Dictionary modules) 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)); } } } @@ -274,4 +270,9 @@ public class ModuleGraph(Dictionary modules) } } } -} \ No newline at end of file +} + +public record Manifest(int Version, IReadOnlyList Modules); +public record ManifestModule(string Name, Dictionary CustomTypes, Dictionary Identifiers); +public record ManifestCustomTypeInfo(string EncodedType, bool Exported); +public record ManifestIdentifierInfo(string EncodedType, bool Exported); \ No newline at end of file diff --git a/compiler/NubType.cs b/compiler/NubType.cs index 96c415a..7a0e871 100644 --- a/compiler/NubType.cs +++ b/compiler/NubType.cs @@ -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(); + 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(); + 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 diff --git a/compiler/Program.cs b/compiler/Program.cs index 8fb08f9..82fbb3e 100644 --- a/compiler/Program.cs +++ b/compiler/Program.cs @@ -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 zip = new ZipArchive(fs, ZipArchiveMode.Create); @@ -174,6 +174,8 @@ static void WriteNublib(string outputPath, string archivePath, ModuleGraph.Manif WriteIndented = true, }); + File.WriteAllText(".build/manifest.json", serialized); + var manifestEntry = zip.CreateEntry("manifest.json"); 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"); - ModuleGraph.Manifest manifest; + Manifest manifest; using (var reader = new StreamReader(manifestEntry.Open())) { var json = reader.ReadToEnd(); - manifest = JsonSerializer.Deserialize(json) ?? throw new InvalidDataException("Failed to deserialize manifest.json"); + manifest = JsonSerializer.Deserialize(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"); @@ -214,4 +216,4 @@ static NublibLoadResult ReadNublib(string nublibPath) return new NublibLoadResult(manifest, tempArchivePath); } -public record NublibLoadResult(ModuleGraph.Manifest Manifest, string ArchivePath); +public record NublibLoadResult(Manifest Manifest, string ArchivePath); diff --git a/examples/math/.build/manifest.json b/examples/math/.build/manifest.json new file mode 100644 index 0000000..19a7145 --- /dev/null +++ b/examples/math/.build/manifest.json @@ -0,0 +1,15 @@ +{ + "version": 1, + "modules": [ + { + "name": "math", + "customTypes": {}, + "identifiers": { + "add": { + "encodedType": "F(I(32),I(32),I(32))", + "exported": true + } + } + } + ] +} \ No newline at end of file diff --git a/examples/math/.build/out.a b/examples/math/.build/out.a index 1032a054425afe26ee76ab9a06d152db51def660..967be10845705ff879edf97fbf96e69e0141c75a 100644 GIT binary patch delta 49 pcmaFI^^R*oq=2b`fw_rAvQe^Gin)QMspZDZLPiY1&94|+m;rD*4qE^K delta 49 pcmaFI^^R*oq(E}AaayuvikXFlp;3~dLCVI=LPiY1&94|+m;soI56J)k diff --git a/examples/math/.build/out.c b/examples/math/.build/out.c index 787fadd..ca42bc4 100644 --- a/examples/math/.build/out.c +++ b/examples/math/.build/out.c @@ -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); diff --git a/examples/math/.build/out.nublib b/examples/math/.build/out.nublib index 0ef493896b49f8679c5ef773fbbb41075d3c6a1e..341b86511bd33b2f5d9f43c707b3d0954f02a1a9 100644 GIT binary patch literal 763 zcmWIWW@Zs#U|`^2aM|h=Gv{H+he{x?9f)~>I5#mbGcC2aL@%p2KhLLYBiA7V5!e4u z{d7|Tw{M@uC0jB{?~y=_KhKOMD*6jr{_IY9UBo}9SUb$~=1~SKi5R8n{V5mrKFZqL z@L=t}M1!eoF5a(;UcXgRN5}E*Y0pzxc(fe}`z3`Fz zJUMx$`{LvJCu|GrBwY5G#NB6myOb@(f-T|LpGWq#E`_##?lH_<+@Lw%|H2OGf-v^p z$}7^dvyT1cW6w1>=kU6a=T)oYgY6a>+E46sr)s}8Oux4^CVtzkFJ@f%e>=(@mH)Q| z?vLEt5%J*h{Tb6urLX?j+cN95Xv~xtugCmCe@gxuHJq{kl09j&&=+pbD$`xeNnBU{ zy{OmNuW0PJ{=WB1XbV+y9cK)>m$i%%Xbs0B=Sn5oX*84;Zgtu%r=0p(I0et?20iqLG1N aN#hbA6P!8%yjj^m!c0Jz2c*lHKs*5AqCHFi literal 789 zcmWIWW@Zs#U|`^2*s{qh=5(;*r71w(DWef!16!0`V+GeZE1^N&CM6}Fy{ zfgz8TfdPmZax#B{+4@GI=`VU#OaEBl`)Shmy*2m4XWdI*c-hJ$cjEjLe`bB( z&v{bpN}ew30fvIB@2;)3d%RYw`0lF5DbnZG?T*!mD7$-V2gj~CY|)2hw-xU^e{s{> zdo5Rj_>XQDzAT_-D`D|t%axC}+~rPv=UMh~#*IqHmoGB<*GxS%wKVDJN?+Zi^f!A_ zBh7>uI2sBWmKL$9^`swMSF*)7v%HHSd>JC>Akz`k7Vg?$0?_9hK$29h)|*@cp#rT|LGZsze&C8sAsv z^4;Rw;qLwPRN9f5#k$wemQ61^wBT{;A3l>Wc@kfvuDYG5;s1YZ(wdts$K;P)iCLcz zRg^4MFY|c$>u^S&f6n_Aclz|yS-P!1_NQS6(^kR1-Jhh5lE3`g>$2|ejwyzve=m3Z z;=ZYTRlha3@}ld`d6T|}R2}92Bvx_llfZtJi^{S3k6!H+R=8B}`uOXwvqxWKe@ZCs z_{SXJ&B!Fej5|pJqZJI6G=eCU1d6T|Jvl%$GB7M@+z(`e6GwnID=;N7FfajO9*~~M H1mXbzi_Td- diff --git a/examples/math/.build/out.o b/examples/math/.build/out.o index f8e2349f273e7d831a54e9e97b288ec4c296aaa1..20786e31d15a2288d91c3df6092d805de56d5953 100644 GIT binary patch delta 29 kcmX@Xd4h9;38R3ifq}V+MY2({S&F%VrK#m+7seK50Ddh8?*IS* delta 29 kcmX@Xd4h9;38O%AvT<6nWr~@Fg`rWBp+U-K7seK50E*KHrT_o{ diff --git a/examples/program/.build/out b/examples/program/.build/out new file mode 100755 index 0000000000000000000000000000000000000000..4eace4f95ba567a60356ae4fe47ca986daa3e977 GIT binary patch literal 15360 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 +#include +#include +#include +#include + +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); + } +} + diff --git a/examples/program/main.nub b/examples/program/main.nub index 99f5d86..4693c99 100644 --- a/examples/program/main.nub +++ b/examples/program/main.nub @@ -2,5 +2,5 @@ module main func main(): i32 { - return math::add(1, 2) + return math::add(1 2) } \ No newline at end of file diff --git a/compiler/test.nub b/examples/test/test.nub similarity index 100% rename from compiler/test.nub rename to examples/test/test.nub diff --git a/compiler/test2.nub b/examples/test/test2.nub similarity index 100% rename from compiler/test2.nub rename to examples/test/test2.nub