This commit is contained in:
nub31
2025-07-05 18:57:50 +02:00
parent f15b37caee
commit c661800f08
5 changed files with 225 additions and 152 deletions

View File

@@ -127,7 +127,7 @@ public static class QBEGenerator
return $"${funcDef.CallName}"; return $"${funcDef.CallName}";
} }
private static string ImplFuncName(BoundTraitImplNode implDef, string funcName) private static string ImplFuncName()
{ {
return $"$impl{++_implFuncNameIndex}"; return $"$impl{++_implFuncNameIndex}";
} }
@@ -405,22 +405,12 @@ public static class QBEGenerator
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
} }
case NubCustomType customType: case NubStructType structType:
{ {
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name); var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
if (structDef.HasValue) return structDef.Fields.Max(f => AlignmentOf(f.Type));
{
return structDef.Value.Fields.Max(f => AlignmentOf(f.Type));
}
var traitDef = _definitionTable.LookupTrait(customType.Namespace, customType.Name);
if (traitDef.HasValue)
{
return 8;
}
throw new UnreachableException();
} }
case NubTraitType:
case NubPointerType: case NubPointerType:
case NubArrayType: case NubArrayType:
case NubCStringType: case NubCStringType:
@@ -452,15 +442,13 @@ public static class QBEGenerator
_ => throw new ArgumentOutOfRangeException() _ => throw new ArgumentOutOfRangeException()
}; };
} }
case NubCustomType customType: case NubStructType structType:
{
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
if (structDef.HasValue)
{ {
var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
var size = 0; var size = 0;
var maxAlignment = 1; var maxAlignment = 1;
foreach (var field in structDef.Value.Fields) foreach (var field in structDef.Fields)
{ {
var fieldAlignment = AlignmentOf(field.Type); var fieldAlignment = AlignmentOf(field.Type);
maxAlignment = Math.Max(maxAlignment, fieldAlignment); maxAlignment = Math.Max(maxAlignment, fieldAlignment);
@@ -473,15 +461,8 @@ public static class QBEGenerator
return size; return size;
} }
case NubTraitType:
var traitDef = _definitionTable.LookupTrait(customType.Namespace, customType.Name);
if (traitDef.HasValue)
{
return 16; return 16;
}
throw new UnreachableException();
}
case NubPointerType: case NubPointerType:
case NubArrayType: case NubArrayType:
case NubCStringType: case NubCStringType:
@@ -800,18 +781,22 @@ public static class QBEGenerator
_writer.WriteDebugLocation(expression); _writer.WriteDebugLocation(expression);
return expression switch return expression switch
{ {
BoundAddressOfNode addressOf => EmitAddressOf(addressOf),
BoundAnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc),
BoundArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
BoundArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer), BoundArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
BoundBinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
BoundDereferenceNode dereference => EmitDereference(dereference),
BoundFuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
BoundIdentifierNode identifier => EmitIdentifier(identifier),
BoundLiteralNode literal => EmitLiteral(literal),
BoundStructInitializerNode structInitializer => EmitStructInitializer(structInitializer), BoundStructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
BoundAddressOfNode addressOf => EmitAddressOf(addressOf),
BoundDereferenceNode dereference => EmitDereference(dereference),
BoundAnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc),
BoundBinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
BoundFuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
BoundExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
BoundLocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
BoundVariableIdentNode variableIdent => EmitVariableIdent(variableIdent),
BoundLiteralNode literal => EmitLiteral(literal),
BoundUnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression), BoundUnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
BoundMemberAccessNode memberAccess => EmitMemberAccess(memberAccess), BoundStructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
BoundTraitFuncAccessNode traitFuncAccess => EmitTraitFuncAccess(traitFuncAccess),
BoundTraitImplFuncAccessNode traitImplFuncAccess => EmitTraitImplFuncAccess(traitImplFuncAccess),
BoundArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
_ => throw new ArgumentOutOfRangeException(nameof(expression)) _ => throw new ArgumentOutOfRangeException(nameof(expression))
}; };
} }
@@ -1011,19 +996,21 @@ public static class QBEGenerator
}; };
} }
private static Val EmitIdentifier(BoundIdentifierNode identifier) private static Val EmitExternFuncIdent(BoundExternFuncIdentNode externFuncIdent)
{ {
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_syntaxTree.Namespace), identifier.Name).TryGetValue(out var func)) var func = _definitionTable.LookupExternFunc(externFuncIdent.Namespace, externFuncIdent.Name);
{ return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct);
return new Val(FuncName(func), identifier.Type, ValKind.Direct);
} }
if (!identifier.Namespace.HasValue) private static Val EmitLocalFuncIdent(BoundLocalFuncIdentNode localFuncIdent)
{ {
return _variables.Single(v => v.Name == identifier.Name).Val; var func = _definitionTable.LookupExternFunc(localFuncIdent.Namespace, localFuncIdent.Name);
return new Val(ExternFuncName(func), localFuncIdent.Type, ValKind.Direct);
} }
throw new UnreachableException(); private static Val EmitVariableIdent(BoundVariableIdentNode variableIdent)
{
return _variables.Single(v => v.Name == variableIdent.Name).Val;
} }
private static Val EmitLiteral(BoundLiteralNode literal) private static Val EmitLiteral(BoundLiteralNode literal)
@@ -1115,7 +1102,7 @@ public static class QBEGenerator
throw new UnreachableException(); throw new UnreachableException();
} }
var structDefinition = _definitionTable.LookupStruct(structType.Namespace, structType.Name).GetValue(); var @struct = _definitionTable.LookupStruct(structType.Namespace, structType.Name);
if (destination == null) if (destination == null)
{ {
@@ -1124,7 +1111,7 @@ public static class QBEGenerator
_writer.Indented($"{destination} =l alloc8 {size}"); _writer.Indented($"{destination} =l alloc8 {size}");
} }
foreach (var field in structDefinition.Fields) foreach (var field in @struct.Fields)
{ {
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression)) if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
{ {
@@ -1134,7 +1121,7 @@ public static class QBEGenerator
Debug.Assert(valueExpression != null); Debug.Assert(valueExpression != null);
var offset = TmpName(); var offset = TmpName();
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDefinition, field.Name)}"); _writer.Indented($"{offset} =l add {destination}, {OffsetOf(@struct, field.Name)}");
EmitCopyIntoOrInitialize(valueExpression, offset); EmitCopyIntoOrInitialize(valueExpression, offset);
} }
@@ -1188,70 +1175,40 @@ public static class QBEGenerator
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported"); throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
} }
private static Val EmitMemberAccess(BoundMemberAccessNode memberAccess) private static Val EmitStructFieldAccess(BoundStructFieldAccessNode structFieldAccess)
{ {
var item = EmitUnwrap(EmitExpression(memberAccess.Expression)); var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
var implementation = _definitionTable.LookupTraitImplementationForType(memberAccess.Expression.Type, memberAccess.Member); var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Namespace, structFieldAccess.StructType.Name);
if (implementation.HasValue) var offset = OffsetOf(structDef, structFieldAccess.Field);
{
var name = ImplFuncName(implementation.Value.Item1, memberAccess.Member);
_implFunctions.TryAdd(implementation.Value.Item2, name);
return new Val(name, memberAccess.Type, ValKind.Direct, new MethodCallContext(item, memberAccess.Expression.Type));
}
var output = TmpName(); var output = TmpName();
_writer.Indented($"{output} =l add {target}, {offset}");
if (memberAccess.Expression.Type is NubCustomType customType)
{
var function = _definitionTable.LookupFunctionOnTrait(customType.Namespace, customType.Name, memberAccess.Member);
if (function.HasValue)
{
throw new NotImplementedException("VTable lookup is not implemented");
}
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
if (structDef.HasValue)
{
var offset = OffsetOf(structDef.Value, memberAccess.Member);
_writer.Indented($"{output} =l add {item}, {offset}");
if (memberAccess.Type is NubCustomType inner)
{
// If the accessed member is an inline struct, it will not be a pointer // If the accessed member is an inline struct, it will not be a pointer
if (_definitionTable.LookupStruct(inner.Namespace, inner.Name).HasValue) if (structFieldAccess.Type is NubStructType)
{ {
return new Val(output, memberAccess.Type, ValKind.Direct); return new Val(output, structFieldAccess.Type, ValKind.Direct);
}
} }
return new Val(output, memberAccess.Type, ValKind.Pointer); return new Val(output, structFieldAccess.Type, ValKind.Pointer);
}
} }
if (memberAccess.Member == "count") private static Val EmitTraitFuncAccess(BoundTraitFuncAccessNode traitFuncAccess)
{ {
switch (memberAccess.Expression.Type) throw new NotImplementedException();
{
case NubArrayType:
{
_writer.Indented($"{output} =l loadl {item}");
return new Val(output, memberAccess.Type, ValKind.Direct);
}
case NubStringType:
{
_writer.Indented($"{output} =l call $nub_string_length(l {item})");
return new Val(output, memberAccess.Type, ValKind.Direct);
}
case NubCStringType:
{
_writer.Indented($"{output} =l call $nub_cstring_length(l {item})");
return new Val(output, memberAccess.Type, ValKind.Direct);
}
}
} }
throw new UnreachableException(); private static Val EmitTraitImplFuncAccess(BoundTraitImplFuncAccessNode traitImplFuncAccess)
{
var target = EmitExpression(traitImplFuncAccess.Target);
var impl = _definitionTable.LookupTraitImpl(traitImplFuncAccess.Target.Type);
var funcImpl = _definitionTable.LookupTraitFuncImpl(impl, traitImplFuncAccess.FuncName);
var name = ImplFuncName();
_implFunctions.TryAdd(funcImpl, name);
return new Val(name, traitImplFuncAccess.Type, ValKind.Direct, new MethodCallContext(target));
} }
private static Val EmitFuncCall(BoundFuncCallNode funcCall) private static Val EmitFuncCall(BoundFuncCallNode funcCall)
@@ -1263,7 +1220,8 @@ public static class QBEGenerator
if (expression.FuncCallContext != null) if (expression.FuncCallContext != null)
{ {
parameterStrings.Add($"{FuncQBETypeName(expression.FuncCallContext.ThisArgType)} {expression.FuncCallContext.ThisArgName}"); var thisArg = EmitUnwrap(expression.FuncCallContext.ThisArg);
parameterStrings.Add($"{FuncQBETypeName(expression.FuncCallContext.ThisArg.Type)} {thisArg}");
} }
foreach (var parameter in funcCall.Parameters) foreach (var parameter in funcCall.Parameters)
@@ -1316,7 +1274,7 @@ internal class Variable(string name, Val val)
internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null); internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null);
internal record MethodCallContext(string ThisArgName, NubType ThisArgType); internal record MethodCallContext(Val ThisArg);
internal enum ValKind internal enum ValKind
{ {

View File

@@ -1,3 +1,4 @@
using System.Diagnostics;
using Common; using Common;
using Syntax.Diagnostics; using Syntax.Diagnostics;
using Syntax.Node; using Syntax.Node;
@@ -49,11 +50,11 @@ public sealed class Binder
{ {
return node switch return node switch
{ {
ExternFuncNode definition => BindExternFuncDefinition(definition), ExternFuncNode topLevel => BindExternFuncDefinition(topLevel),
TraitImplNode definition => BindTraitImplementation(definition), TraitImplNode topLevel => BindTraitImplementation(topLevel),
TraitNode definition => BindTraitDefinition(definition), TraitNode topLevel => BindTraitDefinition(topLevel),
LocalFuncNode definition => BindLocalFuncDefinition(definition), LocalFuncNode topLevel => BindLocalFuncDefinition(topLevel),
StructNode definition => BindStruct(definition), StructNode topLevel => BindStruct(topLevel),
_ => throw new ArgumentOutOfRangeException(nameof(node)) _ => throw new ArgumentOutOfRangeException(nameof(node))
}; };
} }
@@ -70,7 +71,7 @@ public sealed class Binder
_variables[parameter.Name] = parameter.Type; _variables[parameter.Name] = parameter.Type;
} }
functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, function.Parameters, function.ReturnType, BindBlock(function.Body))); functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, function.Parameters, BindType(function.ReturnType), BindBlock(function.Body)));
} }
return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions); return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions);
@@ -82,7 +83,7 @@ public sealed class Binder
foreach (var func in node.Functions) foreach (var func in node.Functions)
{ {
functions.Add(new BoundTraitFuncNode(node.Tokens, func.Name, func.Parameters, func.ReturnType)); functions.Add(new BoundTraitFuncNode(node.Tokens, func.Name, func.Parameters, BindType(func.ReturnType)));
} }
return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions); return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions);
@@ -109,13 +110,13 @@ public sealed class Binder
private BoundExternFuncNode BindExternFuncDefinition(ExternFuncNode node) private BoundExternFuncNode BindExternFuncDefinition(ExternFuncNode node)
{ {
return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, node.Parameters, node.ReturnType); return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, node.Parameters, BindType(node.ReturnType));
} }
private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node) private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node)
{ {
_variables.Clear(); _variables.Clear();
_functionReturnType = node.ReturnType; _functionReturnType = BindType(node.ReturnType);
foreach (var parameter in node.Parameters) foreach (var parameter in node.Parameters)
{ {
@@ -124,7 +125,7 @@ public sealed class Binder
var body = BindBlock(node.Body); var body = BindBlock(node.Body);
return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, node.ReturnType, node.Exported); return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, node.Parameters, body, BindType(node.ReturnType), node.Exported);
} }
private BoundBlock BindBlock(BlockNode node) private BoundBlock BindBlock(BlockNode node)
@@ -269,7 +270,7 @@ public sealed class Binder
var body = BindBlock(expression.Body); var body = BindBlock(expression.Body);
return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(expression.ReturnType, parameterTypes), expression.Parameters, body, expression.ReturnType); return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(BindType(expression.ReturnType), parameterTypes), expression.Parameters, body, BindType(expression.ReturnType));
} }
private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression) private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression)
@@ -303,7 +304,7 @@ public sealed class Binder
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Expression);
var funcType = (NubFuncType)boundExpression.Type; var funcType = (NubFuncType)boundExpression.Type;
var returnType = ((NubFuncType)boundExpression.Type).ReturnType; var returnType = BindType(funcType.ReturnType);
var parameters = new List<BoundExpressionNode>(); var parameters = new List<BoundExpressionNode>();
@@ -322,9 +323,10 @@ public sealed class Binder
return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters); return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters);
} }
private BoundIdentifierNode BindIdentifier(IdentifierNode expression) private BoundExpressionNode BindIdentifier(IdentifierNode expression)
{ {
var localFuncs = _definitionTable.LookupLocalFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray(); var @namespace = expression.Namespace.Or(_syntaxTree.Namespace);
var localFuncs = _definitionTable.LookupLocalFunc(@namespace, expression.Name).ToArray();
if (localFuncs.Length > 0) if (localFuncs.Length > 0)
{ {
if (localFuncs.Length > 1) if (localFuncs.Length > 1)
@@ -334,11 +336,11 @@ public sealed class Binder
var localFunc = localFuncs[0]; var localFunc = localFuncs[0];
var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList()); var type = new NubFuncType(BindType(localFunc.ReturnType), localFunc.Parameters.Select(p => p.Type).ToList());
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); return new BoundLocalFuncIdentNode(expression.Tokens, type, @namespace, expression.Name);
} }
var externFuncs = _definitionTable.LookupExternFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name).ToArray(); var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray();
if (externFuncs.Length > 0) if (externFuncs.Length > 0)
{ {
if (externFuncs.Length > 1) if (externFuncs.Length > 1)
@@ -348,13 +350,13 @@ public sealed class Binder
var externFunc = externFuncs[0]; var externFunc = externFuncs[0];
var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList()); var type = new NubFuncType(BindType(externFunc.ReturnType), externFunc.Parameters.Select(p => p.Type).ToList());
return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); return new BoundExternFuncIdentNode(expression.Tokens, type, @namespace, expression.Name);
} }
if (!expression.Namespace.HasValue) if (!expression.Namespace.HasValue)
{ {
return new BoundIdentifierNode(expression.Tokens, _variables[expression.Name], expression.Namespace, expression.Name); return new BoundVariableIdentNode(expression.Tokens, _variables[expression.Name], expression.Name);
} }
throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build()); throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build());
@@ -374,9 +376,9 @@ public sealed class Binder
return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind); return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind);
} }
private BoundMemberAccessNode BindMemberAccess(MemberAccessNode expression) private BoundExpressionNode BindMemberAccess(MemberAccessNode expression)
{ {
var boundExpression = BindExpression(expression.Expression); var boundExpression = BindExpression(expression.Target);
var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray(); var traitFuncImpls = _definitionTable.LookupTraitImpl(boundExpression.Type).SelectMany(x => _definitionTable.LookupTraitFuncImpl(x, expression.Member)).ToArray();
@@ -389,8 +391,8 @@ public sealed class Binder
var impl = traitFuncImpls[0]; var impl = traitFuncImpls[0];
var type = new NubFuncType(impl.ReturnType, impl.Parameters.Select(p => p.Type).ToList()); var type = new NubFuncType(BindType(impl.ReturnType), impl.Parameters.Select(p => BindType(p.Type)).ToList());
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); return new BoundTraitImplFuncAccessNode(expression.Tokens, type, boundExpression, expression.Member);
} }
if (boundExpression.Type is NubCustomType customType) if (boundExpression.Type is NubCustomType customType)
@@ -415,8 +417,8 @@ public sealed class Binder
var traitFunc = traitFuncs[0]; var traitFunc = traitFuncs[0];
var type = new NubFuncType(traitFunc.ReturnType, traitFunc.Parameters.Select(p => p.Type).ToList()); var type = new NubFuncType(BindType(traitFunc.ReturnType), traitFunc.Parameters.Select(p => BindType(p.Type)).ToList());
return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); return new BoundTraitFuncAccessNode(expression.Tokens, type, new NubTraitType(trait.Namespace, trait.Name), boundExpression, expression.Member);
} }
} }
@@ -440,16 +442,11 @@ public sealed class Binder
var field = fields[0]; var field = fields[0];
return new BoundMemberAccessNode(expression.Tokens, field.Type, boundExpression, expression.Member); return new BoundStructFieldAccessNode(expression.Tokens, field.Type, new NubStructType(@struct.Namespace, @struct.Name), boundExpression, expression.Member);
} }
} }
} }
if (boundExpression.Type is NubStringType or NubCStringType or NubArrayType && expression.Member == "count")
{
return new BoundMemberAccessNode(expression.Tokens, NubPrimitiveType.U64, boundExpression, expression.Member);
}
throw new BindException(Diagnostic.Error($"{boundExpression.Type} has not member with the name {expression.Member}").Build()); throw new BindException(Diagnostic.Error($"{boundExpression.Type} has not member with the name {expression.Member}").Build());
} }
@@ -531,6 +528,48 @@ public sealed class Binder
return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand); return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand);
} }
private NubType BindType(NubType type)
{
if (type is NubCustomType customType)
{
var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray();
if (structs.Length > 1)
{
throw new BindException(Diagnostic.Error($"Struct {type} has multiple definitions").Build());
}
var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray();
if (traits.Length > 1)
{
throw new BindException(Diagnostic.Error($"Trait {type} has multiple definitions").Build());
}
if (structs.Length == 0 && traits.Length == 0)
{
throw new BindException(Diagnostic.Error($"Failed to resolve type {type} to a struct or trait").Build());
}
if (structs.Length > 0 && traits.Length > 0)
{
throw new BindException(Diagnostic.Error($"Unable to determine if type {type} is a struct or trait").WithHelp($"Make {type} is not defined as bot a struct and trait").Build());
}
if (structs.Length == 1)
{
return new NubStructType(customType.Namespace, customType.Name);
}
if (traits.Length == 1)
{
return new NubTraitType(customType.Namespace, customType.Name);
}
throw new UnreachableException();
}
return type;
}
} }
public class BindException : Exception public class BindException : Exception

View File

@@ -61,3 +61,63 @@ public sealed class DefinitionTable
return trait.Functions.Where(x => x.Name == name); return trait.Functions.Where(x => x.Name == name);
} }
} }
public sealed class BoundDefinitionTable
{
private readonly List<BoundTopLevelNode> _topLevelNodes;
public BoundDefinitionTable(IEnumerable<BoundSyntaxTree> syntaxTrees)
{
_topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList();
}
public BoundLocalFuncNode LookupLocalFunc(string @namespace, string name)
{
return _topLevelNodes
.OfType<BoundLocalFuncNode>()
.First(x => x.Namespace == @namespace && x.Name == name);
}
public BoundExternFuncNode LookupExternFunc(string @namespace, string name)
{
return _topLevelNodes
.OfType<BoundExternFuncNode>()
.First(x => x.Namespace == @namespace && x.Name == name);
}
public BoundStructNode LookupStruct(string @namespace, string name)
{
return _topLevelNodes
.OfType<BoundStructNode>()
.First(x => x.Namespace == @namespace && x.Name == name);
}
public BoundStructFieldNode LookupStructField(BoundStructNode structNode, string field)
{
return structNode.Fields.First(x => x.Name == field);
}
public BoundTraitImplNode LookupTraitImpl(NubType itemType)
{
return _topLevelNodes
.OfType<BoundTraitImplNode>()
.First(x => x.TraitType == itemType);
}
public BoundTraitFuncImplNode LookupTraitFuncImpl(BoundTraitImplNode traitImpl, string name)
{
return traitImpl.Functions.First(x => x.Name == name);
}
public BoundTraitNode LookupTrait(string @namespace, string name)
{
return _topLevelNodes
.OfType<BoundTraitNode>()
.First(x => x.Namespace == @namespace && x.Name == name);
}
public BoundTraitFuncNode LookupTraitFunc(BoundTraitNode trait, string name)
{
return trait.Functions.First(x => x.Name == name);
}
}

View File

@@ -36,7 +36,9 @@ public record FuncCallNode(IEnumerable<Token> Tokens, ExpressionNode Expression,
public record BoundFuncCallNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, List<BoundExpressionNode> Parameters) : BoundExpressionNode(Tokens, Type); public record BoundFuncCallNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, List<BoundExpressionNode> Parameters) : BoundExpressionNode(Tokens, Type);
public record IdentifierNode(IEnumerable<Token> Tokens, Optional<string> Namespace, string Name) : ExpressionNode(Tokens); public record IdentifierNode(IEnumerable<Token> Tokens, Optional<string> Namespace, string Name) : ExpressionNode(Tokens);
public record BoundIdentifierNode(IEnumerable<Token> Tokens, NubType Type, Optional<string> Namespace, string Name) : BoundExpressionNode(Tokens, Type); public record BoundVariableIdentNode(IEnumerable<Token> Tokens, NubType Type, string Name) : BoundExpressionNode(Tokens, Type);
public record BoundLocalFuncIdentNode(IEnumerable<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type);
public record BoundExternFuncIdentNode(IEnumerable<Token> Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type);
public record ArrayInitializerNode(IEnumerable<Token> Tokens, ExpressionNode Capacity, NubType ElementType) : ExpressionNode(Tokens); public record ArrayInitializerNode(IEnumerable<Token> Tokens, ExpressionNode Capacity, NubType ElementType) : ExpressionNode(Tokens);
public record BoundArrayInitializerNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type); public record BoundArrayInitializerNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type);
@@ -53,8 +55,10 @@ public record BoundAddressOfNode(IEnumerable<Token> Tokens, NubType Type, BoundE
public record LiteralNode(IEnumerable<Token> Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens); public record LiteralNode(IEnumerable<Token> Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens);
public record BoundLiteralNode(IEnumerable<Token> Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type); public record BoundLiteralNode(IEnumerable<Token> Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type);
public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Expression, string Member) : ExpressionNode(Tokens); public record MemberAccessNode(IEnumerable<Token> Tokens, ExpressionNode Target, string Member) : ExpressionNode(Tokens);
public record BoundMemberAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Expression, string Member) : BoundExpressionNode(Tokens, Type); public record BoundStructFieldAccessNode(IEnumerable<Token> Tokens, NubType Type, NubStructType StructType, BoundExpressionNode Target, string Field) : BoundExpressionNode(Tokens, Type);
public record BoundTraitImplFuncAccessNode(IEnumerable<Token> Tokens, NubType Type, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type);
public record BoundTraitFuncAccessNode(IEnumerable<Token> Tokens, NubType Type, NubTraitType TraitType, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type);
public record StructInitializerNode(IEnumerable<Token> Tokens, NubType StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(Tokens); public record StructInitializerNode(IEnumerable<Token> Tokens, NubType StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(Tokens);
public record BoundStructInitializerNode(IEnumerable<Token> Tokens, NubType Type, NubType StructType, Dictionary<string, BoundExpressionNode> Initializers) : BoundExpressionNode(Tokens, Type); public record BoundStructInitializerNode(IEnumerable<Token> Tokens, NubType Type, NubType StructType, Dictionary<string, BoundExpressionNode> Initializers) : BoundExpressionNode(Tokens, Type);

View File

@@ -86,6 +86,18 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name); public override int GetHashCode() => HashCode.Combine(typeof(NubCustomType), Namespace, Name);
} }
public class NubStructType(string @namespace, string name) : NubCustomType(@namespace, name)
{
public override bool Equals(NubType? other) => other is NubStructType custom && Namespace == custom.Namespace && Name == custom.Name;
public override int GetHashCode() => HashCode.Combine(typeof(NubStructType), Namespace, Name);
}
public class NubTraitType(string @namespace, string name) : NubCustomType(@namespace, name)
{
public override bool Equals(NubType? other) => other is NubTraitType custom && Namespace == custom.Namespace && Name == custom.Name;
public override int GetHashCode() => HashCode.Combine(typeof(NubTraitType), Namespace, Name);
}
public class NubPointerType(NubType baseType) : NubSimpleType public class NubPointerType(NubType baseType) : NubSimpleType
{ {
public NubType BaseType { get; } = baseType; public NubType BaseType { get; } = baseType;