Reordering
This commit is contained in:
60
src/compiler/NubLang/Syntax/Binding/DefinitionTable.cs
Normal file
60
src/compiler/NubLang/Syntax/Binding/DefinitionTable.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using NubLang.Syntax.Parsing.Node;
|
||||
|
||||
namespace NubLang.Syntax.Binding;
|
||||
|
||||
public class DefinitionTable
|
||||
{
|
||||
private readonly List<DefinitionSyntax> _definitions;
|
||||
|
||||
public DefinitionTable(IEnumerable<SyntaxTree> syntaxTrees)
|
||||
{
|
||||
_definitions = syntaxTrees.SelectMany(x => x.Definitions).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<LocalFuncSyntax> LookupLocalFunc(string @namespace, string name)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<LocalFuncSyntax>()
|
||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
||||
}
|
||||
|
||||
public IEnumerable<ExternFuncSyntax> LookupExternFunc(string @namespace, string name)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<ExternFuncSyntax>()
|
||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
||||
}
|
||||
|
||||
public IEnumerable<StructSyntax> LookupStruct(string @namespace, string name)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<StructSyntax>()
|
||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
||||
}
|
||||
|
||||
public IEnumerable<StructFieldSyntax> LookupStructField(StructSyntax structNode, string field)
|
||||
{
|
||||
return structNode.Fields.Where(x => x.Name == field);
|
||||
}
|
||||
|
||||
public IEnumerable<TraitFuncImplSyntax> LookupTraitFuncImpl(NubType forType, string name)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<TraitImplSyntax>()
|
||||
.Where(x => x.ForType == forType)
|
||||
.SelectMany(x => x.Functions)
|
||||
.Where(x => x.Name == name);
|
||||
}
|
||||
|
||||
public IEnumerable<TraitSyntax> LookupTrait(string @namespace, string name)
|
||||
{
|
||||
return _definitions
|
||||
.OfType<TraitSyntax>()
|
||||
.Where(x => x.Namespace == @namespace && x.Name == name);
|
||||
}
|
||||
|
||||
public IEnumerable<TraitFuncSyntax> LookupTraitFunc(TraitSyntax trait, string name)
|
||||
{
|
||||
return trait.Functions.Where(x => x.Name == name);
|
||||
}
|
||||
}
|
||||
316
src/compiler/NubLang/Syntax/Binding/NubType.cs
Normal file
316
src/compiler/NubLang/Syntax/Binding/NubType.cs
Normal file
@@ -0,0 +1,316 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NubLang.Generation;
|
||||
|
||||
namespace NubLang.Syntax.Binding;
|
||||
|
||||
public abstract class NubType : IEquatable<NubType>
|
||||
{
|
||||
public bool IsNumber => this is NubPrimitiveType
|
||||
{
|
||||
Kind: PrimitiveTypeKind.I8
|
||||
or PrimitiveTypeKind.I16
|
||||
or PrimitiveTypeKind.I32
|
||||
or PrimitiveTypeKind.I64
|
||||
or PrimitiveTypeKind.U8
|
||||
or PrimitiveTypeKind.U16
|
||||
or PrimitiveTypeKind.U32
|
||||
or PrimitiveTypeKind.U64
|
||||
or PrimitiveTypeKind.F32
|
||||
or PrimitiveTypeKind.F64
|
||||
};
|
||||
|
||||
public bool IsSimpleType([NotNullWhen(true)] out NubSimpleType? simpleType, [NotNullWhen(false)] out NubComplexType? complexType)
|
||||
{
|
||||
if (this is NubSimpleType st)
|
||||
{
|
||||
complexType = null;
|
||||
simpleType = st;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this is NubComplexType ct)
|
||||
{
|
||||
complexType = ct;
|
||||
simpleType = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Type {this} is not a simple type nor a compex type");
|
||||
}
|
||||
|
||||
public abstract int Size(BoundDefinitionTable definitionTable);
|
||||
public abstract int Alignment(BoundDefinitionTable definitionTable);
|
||||
|
||||
public static int AlignTo(int offset, int alignment)
|
||||
{
|
||||
return (offset + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) => obj is NubType other && Equals(other);
|
||||
|
||||
public abstract bool Equals(NubType? other);
|
||||
public abstract override int GetHashCode();
|
||||
public abstract override string ToString();
|
||||
|
||||
public static bool operator ==(NubType? left, NubType? right) => Equals(left, right);
|
||||
public static bool operator !=(NubType? left, NubType? right) => !Equals(left, right);
|
||||
}
|
||||
|
||||
public enum StorageSize
|
||||
{
|
||||
Void,
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
U64,
|
||||
F32,
|
||||
F64
|
||||
}
|
||||
|
||||
public abstract class NubSimpleType : NubType
|
||||
{
|
||||
public abstract StorageSize StorageSize { get; }
|
||||
|
||||
public override int Size(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
return StorageSize switch
|
||||
{
|
||||
StorageSize.I64 or StorageSize.U64 or StorageSize.F64 => 8,
|
||||
StorageSize.I32 or StorageSize.U32 or StorageSize.F32 => 4,
|
||||
StorageSize.I16 or StorageSize.U16 => 2,
|
||||
StorageSize.I8 or StorageSize.U8 => 1,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(StorageSize))
|
||||
};
|
||||
}
|
||||
|
||||
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
return Size(definitionTable);
|
||||
}
|
||||
}
|
||||
|
||||
#region Simple types
|
||||
|
||||
public class NubFuncType(NubType returnType, List<NubType> parameters) : NubSimpleType
|
||||
{
|
||||
public List<NubType> Parameters { get; } = parameters;
|
||||
public NubType ReturnType { get; } = returnType;
|
||||
|
||||
public override StorageSize StorageSize => StorageSize.U64;
|
||||
|
||||
public override string ToString() => $"func({string.Join(", ", Parameters)}): {ReturnType}";
|
||||
public override bool Equals(NubType? other) => other is NubFuncType func && ReturnType.Equals(func.ReturnType) && Parameters.SequenceEqual(func.Parameters);
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var hash = new HashCode();
|
||||
hash.Add(typeof(NubFuncType));
|
||||
hash.Add(ReturnType);
|
||||
foreach (var param in Parameters)
|
||||
{
|
||||
hash.Add(param);
|
||||
}
|
||||
|
||||
return hash.ToHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public class NubPointerType(NubType baseType) : NubSimpleType
|
||||
{
|
||||
public NubType BaseType { get; } = baseType;
|
||||
|
||||
public override StorageSize StorageSize => StorageSize.U64;
|
||||
|
||||
public override string ToString() => "^" + BaseType;
|
||||
public override bool Equals(NubType? other) => other is NubPointerType pointer && BaseType.Equals(pointer.BaseType);
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubPointerType), BaseType);
|
||||
}
|
||||
|
||||
public class NubVoidType : NubSimpleType
|
||||
{
|
||||
public override StorageSize StorageSize => StorageSize.Void;
|
||||
|
||||
public override string ToString() => "void";
|
||||
public override bool Equals(NubType? other) => other is NubVoidType;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubVoidType));
|
||||
}
|
||||
|
||||
public class NubPrimitiveType(PrimitiveTypeKind kind) : NubSimpleType
|
||||
{
|
||||
public PrimitiveTypeKind Kind { get; } = kind;
|
||||
|
||||
public override StorageSize StorageSize => Kind switch
|
||||
{
|
||||
PrimitiveTypeKind.I8 => StorageSize.I8,
|
||||
PrimitiveTypeKind.I16 => StorageSize.I16,
|
||||
PrimitiveTypeKind.I32 => StorageSize.I32,
|
||||
PrimitiveTypeKind.I64 => StorageSize.I64,
|
||||
PrimitiveTypeKind.U8 => StorageSize.U8,
|
||||
PrimitiveTypeKind.U16 => StorageSize.U16,
|
||||
PrimitiveTypeKind.U32 => StorageSize.U32,
|
||||
PrimitiveTypeKind.U64 => StorageSize.U64,
|
||||
PrimitiveTypeKind.F64 => StorageSize.F64,
|
||||
PrimitiveTypeKind.F32 => StorageSize.F32,
|
||||
PrimitiveTypeKind.Bool => StorageSize.U8,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Kind switch
|
||||
{
|
||||
PrimitiveTypeKind.I8 => "i8",
|
||||
PrimitiveTypeKind.I16 => "i16",
|
||||
PrimitiveTypeKind.I32 => "i32",
|
||||
PrimitiveTypeKind.I64 => "i64",
|
||||
|
||||
PrimitiveTypeKind.U8 => "u8",
|
||||
PrimitiveTypeKind.U16 => "u16",
|
||||
PrimitiveTypeKind.U32 => "u32",
|
||||
PrimitiveTypeKind.U64 => "u64",
|
||||
|
||||
PrimitiveTypeKind.F32 => "f32",
|
||||
PrimitiveTypeKind.F64 => "f64",
|
||||
|
||||
PrimitiveTypeKind.Bool => "bool",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(kind), Kind, null)
|
||||
};
|
||||
}
|
||||
|
||||
public override bool Equals(NubType? other) => other is NubPrimitiveType primitive && primitive.Kind == Kind;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubPrimitiveType), Kind.GetHashCode());
|
||||
}
|
||||
|
||||
public enum PrimitiveTypeKind
|
||||
{
|
||||
I64,
|
||||
I32,
|
||||
I16,
|
||||
I8,
|
||||
U64,
|
||||
U32,
|
||||
U16,
|
||||
U8,
|
||||
F64,
|
||||
F32,
|
||||
Bool
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public abstract class NubComplexType : NubType;
|
||||
|
||||
#region Complex types
|
||||
|
||||
public class NubCStringType : NubComplexType
|
||||
{
|
||||
public override int Size(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => Size(definitionTable);
|
||||
|
||||
public override string ToString() => "cstring";
|
||||
public override bool Equals(NubType? other) => other is NubCStringType;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubCStringType));
|
||||
}
|
||||
|
||||
public class NubStringType : NubComplexType
|
||||
{
|
||||
public override int Size(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => Size(definitionTable);
|
||||
|
||||
public override string ToString() => "string";
|
||||
public override bool Equals(NubType? other) => other is NubStringType;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubStringType));
|
||||
}
|
||||
|
||||
public class NubCustomType(string @namespace, string name) : NubComplexType
|
||||
{
|
||||
public string Namespace { get; } = @namespace;
|
||||
public string Name { get; } = name;
|
||||
|
||||
public CustomTypeKind Kind(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
if (definitionTable.GetStructs().Any(x => x.Namespace == Namespace && x.Name == Name))
|
||||
{
|
||||
return CustomTypeKind.Struct;
|
||||
}
|
||||
|
||||
if (definitionTable.GetTraits().Any(x => x.Namespace == Namespace && x.Name == Name))
|
||||
{
|
||||
return CustomTypeKind.Trait;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Definition table does not have any type information for {this}");
|
||||
}
|
||||
|
||||
public override int Size(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
switch (Kind(definitionTable))
|
||||
{
|
||||
case CustomTypeKind.Struct:
|
||||
{
|
||||
var structDef = definitionTable.LookupStruct(Namespace, Name);
|
||||
var size = 0;
|
||||
var maxAlignment = 1;
|
||||
|
||||
foreach (var field in structDef.Fields)
|
||||
{
|
||||
var fieldAlignment = field.Type.Alignment(definitionTable);
|
||||
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
||||
|
||||
size = AlignTo(size, fieldAlignment);
|
||||
size += field.Type.Size(definitionTable);
|
||||
}
|
||||
|
||||
return AlignTo(size, maxAlignment);
|
||||
}
|
||||
case CustomTypeKind.Trait:
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
switch (Kind(definitionTable))
|
||||
{
|
||||
case CustomTypeKind.Struct:
|
||||
return definitionTable.LookupStruct(Namespace, Name).Fields.Max(f => f.Type.Alignment(definitionTable));
|
||||
case CustomTypeKind.Trait:
|
||||
return 8;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString() => $"{Namespace}::{Name}";
|
||||
public override bool Equals(NubType? other) => other is NubCustomType custom && Namespace == custom.Namespace && Name == custom.Name;
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name);
|
||||
}
|
||||
|
||||
public enum CustomTypeKind
|
||||
{
|
||||
Struct,
|
||||
Trait
|
||||
}
|
||||
|
||||
public class NubArrayType(NubType elementType) : NubComplexType
|
||||
{
|
||||
public NubType ElementType { get; } = elementType;
|
||||
|
||||
public override int Size(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => Size(definitionTable);
|
||||
|
||||
public override string ToString() => "[]" + ElementType;
|
||||
|
||||
public override bool Equals(NubType? other) => other is NubArrayType array && ElementType.Equals(array.ElementType);
|
||||
public override int GetHashCode() => HashCode.Combine(typeof(NubArrayType), ElementType);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -2,6 +2,21 @@ using NubLang.Syntax.Tokenization;
|
||||
|
||||
namespace NubLang.Syntax.Parsing.Node;
|
||||
|
||||
public enum PrimitiveTypeSyntaxKind
|
||||
{
|
||||
I64,
|
||||
I32,
|
||||
I16,
|
||||
I8,
|
||||
U64,
|
||||
U32,
|
||||
U16,
|
||||
U8,
|
||||
F64,
|
||||
F32,
|
||||
Bool
|
||||
}
|
||||
|
||||
public abstract record TypeSyntax(IReadOnlyList<Token> Tokens) : SyntaxNode(Tokens);
|
||||
|
||||
public record FuncTypeSyntax(IReadOnlyList<Token> Tokens, IReadOnlyList<TypeSyntax> Parameters, TypeSyntax ReturnType) : TypeSyntax(Tokens);
|
||||
@@ -10,7 +25,7 @@ public record PointerTypeSyntax(IReadOnlyList<Token> Tokens, TypeSyntax BaseType
|
||||
|
||||
public record VoidTypeSyntax(IReadOnlyList<Token> Tokens) : TypeSyntax(Tokens);
|
||||
|
||||
public record PrimitiveTypeSyntax(IReadOnlyList<Token> Tokens, PrimitiveTypeKind Kind) : TypeSyntax(Tokens);
|
||||
public record PrimitiveTypeSyntax(IReadOnlyList<Token> Tokens, PrimitiveTypeSyntaxKind SyntaxKind) : TypeSyntax(Tokens);
|
||||
|
||||
public record CStringTypeSyntax(IReadOnlyList<Token> Tokens) : TypeSyntax(Tokens);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using NubLang.Common;
|
||||
using NubLang.Diagnostics;
|
||||
using NubLang.Syntax.Binding;
|
||||
using NubLang.Syntax.Parsing.Node;
|
||||
using NubLang.Syntax.Tokenization;
|
||||
|
||||
@@ -660,17 +661,17 @@ public sealed class Parser
|
||||
"void" => new VoidTypeSyntax(GetTokens(startIndex)),
|
||||
"string" => new StringTypeSyntax(GetTokens(startIndex)),
|
||||
"cstring" => new CStringTypeSyntax(GetTokens(startIndex)),
|
||||
"i64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.I64),
|
||||
"i32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.I32),
|
||||
"i16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.I16),
|
||||
"i8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.I8),
|
||||
"u64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.U64),
|
||||
"u32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.U32),
|
||||
"u16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.U16),
|
||||
"u8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.U8),
|
||||
"f64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.F64),
|
||||
"f32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.F32),
|
||||
"bool" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeKind.Bool),
|
||||
"i64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I64),
|
||||
"i32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I32),
|
||||
"i16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I16),
|
||||
"i8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.I8),
|
||||
"u64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U64),
|
||||
"u32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U32),
|
||||
"u16" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U16),
|
||||
"u8" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.U8),
|
||||
"f64" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.F64),
|
||||
"f32" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.F32),
|
||||
"bool" => new PrimitiveTypeSyntax(GetTokens(startIndex), PrimitiveTypeSyntaxKind.Bool),
|
||||
_ => ParseCustomType()
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user