libs working
This commit is contained in:
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,4 +270,9 @@ 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);
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
15
examples/math/.build/manifest.json
Normal file
15
examples/math/.build/manifest.json
Normal 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.
@@ -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
BIN
examples/program/.build/out
Executable file
Binary file not shown.
29
examples/program/.build/out.c
Normal file
29
examples/program/.build/out.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -2,5 +2,5 @@ module main
|
|||||||
|
|
||||||
func main(): i32
|
func main(): i32
|
||||||
{
|
{
|
||||||
return math::add(1, 2)
|
return math::add(1 2)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user