....
This commit is contained in:
@@ -198,7 +198,7 @@ public class ModuleGraph
|
|||||||
|
|
||||||
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
|
foreach (var structDef in ast.Definitions.OfType<NodeDefinitionStruct>())
|
||||||
{
|
{
|
||||||
var type = new NubTypeStruct(module.Name, structDef.Name.Ident, structDef.Packed);
|
var type = NubTypeStruct.CreateWithoutFields(structDef.Packed);
|
||||||
var info = new Module.CustomTypeInfo(type, structDef.Exported, Module.Source.Ast);
|
var info = new Module.CustomTypeInfo(type, structDef.Exported, Module.Source.Ast);
|
||||||
module.AddCustomType(structDef.Name.Ident, info);
|
module.AddCustomType(structDef.Name.Ident, info);
|
||||||
}
|
}
|
||||||
@@ -214,8 +214,11 @@ public class ModuleGraph
|
|||||||
if (!module.TryResolveCustomType(structDef.Name.Ident, true, out var customType))
|
if (!module.TryResolveCustomType(structDef.Name.Ident, true, out var customType))
|
||||||
throw new UnreachableException($"{nameof(customType)} should always be registered");
|
throw new UnreachableException($"{nameof(customType)} should always be registered");
|
||||||
|
|
||||||
var fields = structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, ResolveType(f.Type, module.Name))).ToList();
|
if (customType is NubTypeStruct structType)
|
||||||
((NubTypeStruct)customType).ResolveFields(fields);
|
{
|
||||||
|
var fields = structDef.Fields.Select(f => new NubTypeStruct.Field(f.Name.Ident, ResolveType(f.Type, module.Name))).ToList();
|
||||||
|
structType.SetFields(fields);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Compiler;
|
namespace Compiler;
|
||||||
@@ -86,36 +87,61 @@ public class NubTypeString : NubType
|
|||||||
|
|
||||||
public class NubTypeStruct : NubType
|
public class NubTypeStruct : NubType
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
private static readonly Dictionary<Signature, NubTypeStruct> Cache = new();
|
||||||
public string Module { get; }
|
|
||||||
public bool Packed { get; }
|
|
||||||
|
|
||||||
private IReadOnlyList<Field>? _resolvedFields;
|
public static NubTypeStruct Get(bool packed, List<Field> fields)
|
||||||
|
{
|
||||||
public IReadOnlyList<Field> Fields => _resolvedFields ?? throw new InvalidOperationException();
|
var sig = new Signature(packed, fields);
|
||||||
|
|
||||||
public NubTypeStruct(string module, string name, bool packed)
|
if (!Cache.TryGetValue(sig, out var sturctType))
|
||||||
|
Cache[sig] = sturctType = new NubTypeStruct(packed, fields);
|
||||||
|
|
||||||
|
return sturctType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NubTypeStruct(bool packed, List<Field> fields)
|
||||||
|
{
|
||||||
|
Packed = packed;
|
||||||
|
this.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
private NubTypeStruct(bool packed)
|
||||||
{
|
{
|
||||||
Module = module;
|
|
||||||
Name = name;
|
|
||||||
Packed = packed;
|
Packed = packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ResolveFields(IReadOnlyList<Field> fields)
|
public bool Packed { get; }
|
||||||
{
|
|
||||||
if (_resolvedFields != null)
|
|
||||||
throw new InvalidOperationException($"{Name} already resolved");
|
|
||||||
|
|
||||||
_resolvedFields = fields;
|
private IReadOnlyList<Field>? fields;
|
||||||
|
public IReadOnlyList<Field> Fields
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (fields == null)
|
||||||
|
throw new InvalidOperationException("Fields has not been set");
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() => _resolvedFields == null ? $"struct {Module}::{Name} <unresolved>" : $"struct {Module}::{Name} {{ {string.Join(' ', Fields.Select(f => $"{f.Name}: {f.Type}"))} }}";
|
public static NubTypeStruct CreateWithoutFields(bool packed)
|
||||||
|
|
||||||
public class Field(string name, NubType type)
|
|
||||||
{
|
{
|
||||||
public string Name { get; } = name;
|
return new NubTypeStruct(packed);
|
||||||
public NubType Type { get; } = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetFields(List<Field> fields)
|
||||||
|
{
|
||||||
|
if (this.fields != null)
|
||||||
|
throw new InvalidOperationException("Fields can only be set once");
|
||||||
|
|
||||||
|
this.fields = fields;
|
||||||
|
Cache[new Signature(Packed, this.fields)] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => $"struct {{ {string.Join(' ', Fields.Select(f => $"{f.Name}: {f.Type}"))} }}";
|
||||||
|
|
||||||
|
public record Field(string Name, NubType Type);
|
||||||
|
private record Signature(bool Packed, IReadOnlyList<Field> Fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NubTypePointer : NubType
|
public class NubTypePointer : NubType
|
||||||
@@ -167,19 +193,38 @@ public class NubTypeFunc : NubType
|
|||||||
|
|
||||||
public override string ToString() => $"func({string.Join(' ', Parameters)}): {ReturnType}";
|
public override string ToString() => $"func({string.Join(' ', Parameters)}): {ReturnType}";
|
||||||
|
|
||||||
private readonly record struct Signature(IReadOnlyList<NubType> Parameters, NubType ReturnType);
|
private record Signature(IReadOnlyList<NubType> Parameters, NubType ReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class TypeEncoder
|
public class TypeEncoder
|
||||||
{
|
{
|
||||||
public static string Encode(NubType type)
|
public static string Encode(NubType type)
|
||||||
|
{
|
||||||
|
return new TypeEncoder().EncodeRoot(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TypeEncoder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<NubTypeStruct, Definition> structDefinitions = new();
|
||||||
|
|
||||||
|
private string EncodeRoot(NubType type)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
Encode(type, sb);
|
|
||||||
|
EncodeType(sb, type);
|
||||||
|
|
||||||
|
foreach (var definition in structDefinitions.Values.OrderBy(x => x.Index))
|
||||||
|
{
|
||||||
|
Debug.Assert(definition.Encoded != null);
|
||||||
|
sb.Insert(0, definition.Encoded);
|
||||||
|
}
|
||||||
|
|
||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Encode(NubType type, StringBuilder sb)
|
private void EncodeType(StringBuilder sb, NubType type)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
@@ -192,11 +237,15 @@ static class TypeEncoder
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NubTypeUInt u:
|
case NubTypeUInt u:
|
||||||
sb.Append("U(").Append(u.Width).Append(')');
|
sb.Append($"U(");
|
||||||
|
sb.Append(u.Width);
|
||||||
|
sb.Append(')');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NubTypeSInt s:
|
case NubTypeSInt s:
|
||||||
sb.Append("I(").Append(s.Width).Append(')');
|
sb.Append($"I(");
|
||||||
|
sb.Append(s.Width);
|
||||||
|
sb.Append(')');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NubTypeString:
|
case NubTypeString:
|
||||||
@@ -205,34 +254,21 @@ static class TypeEncoder
|
|||||||
|
|
||||||
case NubTypePointer p:
|
case NubTypePointer p:
|
||||||
sb.Append("P(");
|
sb.Append("P(");
|
||||||
Encode(p.To, sb);
|
EncodeType(sb, p.To);
|
||||||
sb.Append(')');
|
sb.Append(')');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NubTypeStruct st:
|
case NubTypeStruct st:
|
||||||
sb.Append("T(");
|
sb.Append(GetOrCreateStructDefinition(st));
|
||||||
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(");
|
||||||
foreach (var parameter in fn.Parameters)
|
for (int i = 0; i < fn.Parameters.Count; i++)
|
||||||
{
|
{
|
||||||
sb.Append(Encode(parameter));
|
EncodeType(sb, fn.Parameters[i]);
|
||||||
sb.Append(',');
|
|
||||||
}
|
}
|
||||||
sb.Append(Encode(fn.ReturnType));
|
EncodeType(sb, fn.ReturnType);
|
||||||
sb.Append(')');
|
sb.Append(')');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -240,13 +276,48 @@ static class TypeEncoder
|
|||||||
throw new NotSupportedException(type.GetType().Name);
|
throw new NotSupportedException(type.GetType().Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetOrCreateStructDefinition(NubTypeStruct st)
|
||||||
|
{
|
||||||
|
if (!structDefinitions.TryGetValue(st, out var definition))
|
||||||
|
{
|
||||||
|
definition = new Definition(structDefinitions.Count);
|
||||||
|
structDefinitions[st] = definition;
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.Append("D(");
|
||||||
|
sb.Append(st.Packed ? '1' : '0');
|
||||||
|
sb.Append('{');
|
||||||
|
for (var i = 0; i < st.Fields.Count; i++)
|
||||||
|
{
|
||||||
|
var field = st.Fields[i];
|
||||||
|
sb.Append(field.Name);
|
||||||
|
sb.Append(':');
|
||||||
|
EncodeType(sb, field.Type);
|
||||||
|
}
|
||||||
|
sb.Append('}');
|
||||||
|
sb.Append(')');
|
||||||
|
|
||||||
|
var encoded = sb.ToString();
|
||||||
|
definition.Encoded = encoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"T({definition.Index})";
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Definition(int index)
|
||||||
|
{
|
||||||
|
public int Index { get; } = index;
|
||||||
|
public string? Encoded { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TypeDecoder
|
public class TypeDecoder
|
||||||
{
|
{
|
||||||
public static NubType Decode(string encoded)
|
public static NubType Decode(string encoded)
|
||||||
{
|
{
|
||||||
return new TypeDecoder(encoded).Decode();
|
return new TypeDecoder(encoded).DecodeRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private TypeDecoder(string encoded)
|
private TypeDecoder(string encoded)
|
||||||
@@ -255,158 +326,198 @@ class TypeDecoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly string encoded;
|
private readonly string encoded;
|
||||||
private int pos;
|
private int index;
|
||||||
|
private readonly List<NubTypeStruct> structDefinitions = new();
|
||||||
|
|
||||||
private NubType Decode()
|
private NubType DecodeRoot()
|
||||||
{
|
{
|
||||||
return Parse();
|
// First pass: Collect all declarations
|
||||||
|
while (TryExpect('D'))
|
||||||
|
{
|
||||||
|
Expect('(');
|
||||||
|
var packedChar = Consume();
|
||||||
|
if (packedChar is not '1' and not '0')
|
||||||
|
throw new Exception("Expected '0' or '1' for struct packing");
|
||||||
|
|
||||||
|
Expect('{');
|
||||||
|
while (TryPeek(out var c))
|
||||||
|
{
|
||||||
|
Consume();
|
||||||
|
if (c == '}')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expect(')');
|
||||||
|
|
||||||
|
structDefinitions.Add(NubTypeStruct.CreateWithoutFields(packedChar == '1'));
|
||||||
|
}
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
var defIndex = 0;
|
||||||
|
|
||||||
|
// Second pass: Set field types
|
||||||
|
while (TryExpect('D'))
|
||||||
|
{
|
||||||
|
var fields = new List<NubTypeStruct.Field>();
|
||||||
|
|
||||||
|
Consume();
|
||||||
|
Consume();
|
||||||
|
Consume();
|
||||||
|
|
||||||
|
while (!TryExpect('}'))
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
while (!TryExpect(':'))
|
||||||
|
{
|
||||||
|
sb.Append(Consume());
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = DecodeType();
|
||||||
|
|
||||||
|
fields.Add(new NubTypeStruct.Field(sb.ToString(), type));
|
||||||
|
}
|
||||||
|
Expect(')');
|
||||||
|
|
||||||
|
structDefinitions[defIndex].SetFields(fields);
|
||||||
|
|
||||||
|
defIndex += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DecodeType();
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubType Parse()
|
private NubType DecodeType()
|
||||||
{
|
{
|
||||||
if (pos >= encoded.Length)
|
var start = Consume();
|
||||||
throw new InvalidOperationException("Unexpected end of string");
|
return start switch
|
||||||
|
|
||||||
char c = encoded[pos++];
|
|
||||||
return c switch
|
|
||||||
{
|
{
|
||||||
'V' => NubTypeVoid.Instance,
|
'V' => NubTypeVoid.Instance,
|
||||||
'B' => NubTypeBool.Instance,
|
'B' => NubTypeBool.Instance,
|
||||||
|
'U' => DecodeUInt(),
|
||||||
|
'I' => DecodeSInt(),
|
||||||
'S' => NubTypeString.Instance,
|
'S' => NubTypeString.Instance,
|
||||||
'U' => ParseUInt(),
|
'P' => DecodePointer(),
|
||||||
'I' => ParseSInt(),
|
'F' => DecodeFunc(),
|
||||||
'P' => ParsePointer(),
|
'T' => DecodeStruct(),
|
||||||
'T' => ParseStruct(),
|
_ => throw new Exception($"'{start}' is not a valid start to a type")
|
||||||
'F' => ParseFunc(),
|
|
||||||
_ => throw new NotSupportedException($"Unknown type code '{c}' at position {pos - 1}")
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubTypeUInt ParseUInt()
|
private NubTypeUInt DecodeUInt()
|
||||||
{
|
{
|
||||||
ExpectChar('(');
|
Expect('(');
|
||||||
int width = ReadNumber();
|
var width = ExpectInt();
|
||||||
ExpectChar(')');
|
Expect(')');
|
||||||
return NubTypeUInt.Get(width);
|
return NubTypeUInt.Get(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubTypeSInt ParseSInt()
|
private NubTypeSInt DecodeSInt()
|
||||||
{
|
{
|
||||||
ExpectChar('(');
|
Expect('(');
|
||||||
int width = ReadNumber();
|
var width = ExpectInt();
|
||||||
ExpectChar(')');
|
Expect(')');
|
||||||
return NubTypeSInt.Get(width);
|
return NubTypeSInt.Get(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubTypePointer ParsePointer()
|
private NubTypePointer DecodePointer()
|
||||||
{
|
{
|
||||||
ExpectChar('(');
|
Expect('(');
|
||||||
var to = Parse();
|
var to = DecodeType();
|
||||||
ExpectChar(')');
|
Expect(')');
|
||||||
return NubTypePointer.Get(to);
|
return NubTypePointer.Get(to);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubTypeStruct ParseStruct()
|
private NubTypeFunc DecodeFunc()
|
||||||
{
|
{
|
||||||
ExpectChar('(');
|
var types = new List<NubType>();
|
||||||
int 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}");
|
|
||||||
|
|
||||||
string module = parts[0], name = parts[1];
|
Expect('(');
|
||||||
|
while (!TryExpect(')'))
|
||||||
bool packed = false;
|
|
||||||
if (encoded[pos] == ',')
|
|
||||||
{
|
{
|
||||||
pos += 1;
|
types.Add(DecodeType());
|
||||||
packed = encoded[pos += 1] == '1';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var st = new NubTypeStruct(module, name, packed);
|
return NubTypeFunc.Get(types.Take(types.Count - 1).ToList(), types.Last());
|
||||||
|
|
||||||
ExpectChar('{');
|
|
||||||
|
|
||||||
var fields = new List<NubTypeStruct.Field>();
|
|
||||||
while (encoded[pos] != '}')
|
|
||||||
{
|
|
||||||
int nameStart = pos;
|
|
||||||
while (encoded[pos] != ':') pos += 1;
|
|
||||||
string fieldName = encoded[nameStart..pos];
|
|
||||||
pos += 1;
|
|
||||||
|
|
||||||
var fieldType = Parse();
|
|
||||||
fields.Add(new NubTypeStruct.Field(fieldName, fieldType));
|
|
||||||
|
|
||||||
if (encoded[pos] == ',') pos += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExpectChar('}');
|
|
||||||
ExpectChar(')');
|
|
||||||
|
|
||||||
st.ResolveFields(fields);
|
|
||||||
return st;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NubTypeFunc ParseFunc()
|
private NubTypeStruct DecodeStruct()
|
||||||
{
|
{
|
||||||
ExpectChar('(');
|
Expect('(');
|
||||||
var parameters = new List<NubType>();
|
var index = ExpectInt();
|
||||||
while (true)
|
Expect(')');
|
||||||
|
return structDefinitions[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryPeek(out char c)
|
||||||
|
{
|
||||||
|
if (index >= encoded.Length)
|
||||||
{
|
{
|
||||||
if (encoded[pos] == ')')
|
c = '\0';
|
||||||
{
|
return false;
|
||||||
pos++;
|
}
|
||||||
|
|
||||||
|
c = encoded[index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryConsume(out char c)
|
||||||
|
{
|
||||||
|
if (index >= encoded.Length)
|
||||||
|
{
|
||||||
|
c = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
c = encoded[index];
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private char Consume()
|
||||||
|
{
|
||||||
|
if (!TryConsume(out var c))
|
||||||
|
throw new Exception("Unexpected end of string");
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryExpect(char c)
|
||||||
|
{
|
||||||
|
if (index >= encoded.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (encoded[index] != c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Consume();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Expect(char c)
|
||||||
|
{
|
||||||
|
if (!TryExpect(c))
|
||||||
|
throw new Exception($"Expected '{c}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ExpectInt()
|
||||||
|
{
|
||||||
|
var buf = string.Empty;
|
||||||
|
|
||||||
|
while (TryPeek(out var c))
|
||||||
|
{
|
||||||
|
if (!char.IsDigit(c))
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
var param = Parse();
|
buf += Consume();
|
||||||
parameters.Add(param);
|
|
||||||
|
|
||||||
if (encoded[pos] == ',')
|
|
||||||
{
|
|
||||||
pos += 1;
|
|
||||||
}
|
|
||||||
else if (encoded[pos] == ')')
|
|
||||||
{
|
|
||||||
pos += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"Unexpected char '{encoded[pos]}' in function type at {pos}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameters.Count == 0)
|
return int.Parse(buf);
|
||||||
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 void ExpectChar(char expected)
|
|
||||||
{
|
|
||||||
if (pos >= encoded.Length || encoded[pos] != expected)
|
|
||||||
throw new InvalidOperationException($"Expected '{expected}' at position {pos}");
|
|
||||||
|
|
||||||
pos += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int ReadNumber()
|
|
||||||
{
|
|
||||||
int start = pos;
|
|
||||||
while (pos < encoded.Length && char.IsDigit(encoded[pos])) pos += 1;
|
|
||||||
if (start == pos) throw new InvalidOperationException($"Expected number at position {start}");
|
|
||||||
return int.Parse(encoded[start..pos]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Hashing
|
public static class Hashing
|
||||||
{
|
{
|
||||||
public static ulong Fnv1a64(string text)
|
public static ulong Fnv1a64(string text)
|
||||||
{
|
{
|
||||||
@@ -424,7 +535,7 @@ static class Hashing
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SymbolNameGen
|
public static class SymbolNameGen
|
||||||
{
|
{
|
||||||
public static string Exported(string module, string function, NubType type)
|
public static string Exported(string module, string function, NubType type)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
pushd math
|
pushd math
|
||||||
|
|
||||||
dotnet run --project ../../compiler math.nub --type=lib
|
dotnet run --project ../../compiler math.nub --type=lib
|
||||||
|
pushd .build
|
||||||
|
unzip out.nublib
|
||||||
|
popd
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd program
|
pushd program
|
||||||
|
|
||||||
dotnet run --project ../../compiler main.nub ../math/.build/out.nublib
|
dotnet run --project ../../compiler main.nub ../math/.build/out.nublib
|
||||||
|
|
||||||
popd
|
popd
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
module math
|
module math
|
||||||
|
|
||||||
|
struct vec2 { x: i32 y: i32 }
|
||||||
|
struct vec3 { x: i32 y: i32 z: i32 }
|
||||||
|
struct color { r: i32 g: i32 b: i32 a: i32 }
|
||||||
|
struct example { a: math::vec2 b: math::vec3 c: math::color }
|
||||||
|
|
||||||
export func add(a: i32 b: i32): i32
|
export func add(a: i32 b: i32): i32
|
||||||
{
|
{
|
||||||
return a + b
|
return a + b
|
||||||
|
|||||||
Reference in New Issue
Block a user