diff --git a/src/compiler/Generation/QBE/QBEGenerator.cs b/src/compiler/Generation/QBE/QBEGenerator.cs index 55d8864..d0a07ef 100644 --- a/src/compiler/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/Generation/QBE/QBEGenerator.cs @@ -127,7 +127,7 @@ public static class QBEGenerator return $"${funcDef.CallName}"; } - private static string ImplFuncName(BoundTraitImplNode implDef, string funcName) + private static string ImplFuncName() { return $"$impl{++_implFuncNameIndex}"; } @@ -405,22 +405,12 @@ public static class QBEGenerator _ => throw new ArgumentOutOfRangeException() }; } - case NubCustomType customType: + case NubStructType structType: { - var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name); - if (structDef.HasValue) - { - 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(); + var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name); + return structDef.Fields.Max(f => AlignmentOf(f.Type)); } + case NubTraitType: case NubPointerType: case NubArrayType: case NubCStringType: @@ -452,36 +442,27 @@ public static class QBEGenerator _ => 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 maxAlignment = 1; + + foreach (var field in structDef.Fields) { - var size = 0; - var maxAlignment = 1; + var fieldAlignment = AlignmentOf(field.Type); + maxAlignment = Math.Max(maxAlignment, fieldAlignment); - foreach (var field in structDef.Value.Fields) - { - var fieldAlignment = AlignmentOf(field.Type); - maxAlignment = Math.Max(maxAlignment, fieldAlignment); - - size = AlignTo(size, fieldAlignment); - size += SizeOf(field.Type); - } - - size = AlignTo(size, maxAlignment); - - return size; + size = AlignTo(size, fieldAlignment); + size += SizeOf(field.Type); } - var traitDef = _definitionTable.LookupTrait(customType.Namespace, customType.Name); - if (traitDef.HasValue) - { - return 16; - } + size = AlignTo(size, maxAlignment); - throw new UnreachableException(); + return size; } + case NubTraitType: + return 16; case NubPointerType: case NubArrayType: case NubCStringType: @@ -800,18 +781,22 @@ public static class QBEGenerator _writer.WriteDebugLocation(expression); return expression switch { - BoundAddressOfNode addressOf => EmitAddressOf(addressOf), - BoundAnonymousFuncNode anonymousFunc => EmitAnonymousFunc(anonymousFunc), - BoundArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex), 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), + 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), - 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)) }; } @@ -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)) - { - return new Val(FuncName(func), identifier.Type, ValKind.Direct); - } + var func = _definitionTable.LookupExternFunc(externFuncIdent.Namespace, externFuncIdent.Name); + return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct); + } - if (!identifier.Namespace.HasValue) - { - return _variables.Single(v => v.Name == identifier.Name).Val; - } + private static Val EmitLocalFuncIdent(BoundLocalFuncIdentNode localFuncIdent) + { + 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) @@ -1115,7 +1102,7 @@ public static class QBEGenerator throw new UnreachableException(); } - var structDefinition = _definitionTable.LookupStruct(structType.Namespace, structType.Name).GetValue(); + var @struct = _definitionTable.LookupStruct(structType.Namespace, structType.Name); if (destination == null) { @@ -1124,7 +1111,7 @@ public static class QBEGenerator _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)) { @@ -1134,7 +1121,7 @@ public static class QBEGenerator Debug.Assert(valueExpression != null); 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); } @@ -1188,70 +1175,40 @@ public static class QBEGenerator 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); - if (implementation.HasValue) - { - 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 structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Namespace, structFieldAccess.StructType.Name); + var offset = OffsetOf(structDef, structFieldAccess.Field); var output = TmpName(); + _writer.Indented($"{output} =l add {target}, {offset}"); - if (memberAccess.Expression.Type is NubCustomType customType) + // If the accessed member is an inline struct, it will not be a pointer + if (structFieldAccess.Type is NubStructType) { - 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 (_definitionTable.LookupStruct(inner.Namespace, inner.Name).HasValue) - { - return new Val(output, memberAccess.Type, ValKind.Direct); - } - } - - return new Val(output, memberAccess.Type, ValKind.Pointer); - } + return new Val(output, structFieldAccess.Type, ValKind.Direct); } - if (memberAccess.Member == "count") - { - switch (memberAccess.Expression.Type) - { - 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); - } - } - } + return new Val(output, structFieldAccess.Type, ValKind.Pointer); + } - throw new UnreachableException(); + private static Val EmitTraitFuncAccess(BoundTraitFuncAccessNode traitFuncAccess) + { + throw new NotImplementedException(); + } + + 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) @@ -1263,7 +1220,8 @@ public static class QBEGenerator 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) @@ -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 MethodCallContext(string ThisArgName, NubType ThisArgType); +internal record MethodCallContext(Val ThisArg); internal enum ValKind { diff --git a/src/compiler/Syntax/Binding/Binder.cs b/src/compiler/Syntax/Binding/Binder.cs index fd50575..0f039dd 100644 --- a/src/compiler/Syntax/Binding/Binder.cs +++ b/src/compiler/Syntax/Binding/Binder.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Common; using Syntax.Diagnostics; using Syntax.Node; @@ -49,11 +50,11 @@ public sealed class Binder { return node switch { - ExternFuncNode definition => BindExternFuncDefinition(definition), - TraitImplNode definition => BindTraitImplementation(definition), - TraitNode definition => BindTraitDefinition(definition), - LocalFuncNode definition => BindLocalFuncDefinition(definition), - StructNode definition => BindStruct(definition), + ExternFuncNode topLevel => BindExternFuncDefinition(topLevel), + TraitImplNode topLevel => BindTraitImplementation(topLevel), + TraitNode topLevel => BindTraitDefinition(topLevel), + LocalFuncNode topLevel => BindLocalFuncDefinition(topLevel), + StructNode topLevel => BindStruct(topLevel), _ => throw new ArgumentOutOfRangeException(nameof(node)) }; } @@ -70,7 +71,7 @@ public sealed class Binder _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); @@ -82,7 +83,7 @@ public sealed class Binder 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); @@ -109,13 +110,13 @@ public sealed class Binder 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) { _variables.Clear(); - _functionReturnType = node.ReturnType; + _functionReturnType = BindType(node.ReturnType); foreach (var parameter in node.Parameters) { @@ -124,7 +125,7 @@ public sealed class Binder 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) @@ -269,7 +270,7 @@ public sealed class Binder 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) @@ -303,7 +304,7 @@ public sealed class Binder var boundExpression = BindExpression(expression.Expression); var funcType = (NubFuncType)boundExpression.Type; - var returnType = ((NubFuncType)boundExpression.Type).ReturnType; + var returnType = BindType(funcType.ReturnType); var parameters = new List(); @@ -322,9 +323,10 @@ public sealed class Binder 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 > 1) @@ -334,11 +336,11 @@ public sealed class Binder var localFunc = localFuncs[0]; - var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList()); - return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); + var type = new NubFuncType(BindType(localFunc.ReturnType), localFunc.Parameters.Select(p => p.Type).ToList()); + 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 > 1) @@ -348,13 +350,13 @@ public sealed class Binder var externFunc = externFuncs[0]; - var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList()); - return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); + var type = new NubFuncType(BindType(externFunc.ReturnType), externFunc.Parameters.Select(p => p.Type).ToList()); + return new BoundExternFuncIdentNode(expression.Tokens, type, @namespace, expression.Name); } 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()); @@ -374,9 +376,9 @@ public sealed class Binder 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(); @@ -389,8 +391,8 @@ public sealed class Binder var impl = traitFuncImpls[0]; - var type = new NubFuncType(impl.ReturnType, impl.Parameters.Select(p => p.Type).ToList()); - return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); + var type = new NubFuncType(BindType(impl.ReturnType), impl.Parameters.Select(p => BindType(p.Type)).ToList()); + return new BoundTraitImplFuncAccessNode(expression.Tokens, type, boundExpression, expression.Member); } if (boundExpression.Type is NubCustomType customType) @@ -415,8 +417,8 @@ public sealed class Binder var traitFunc = traitFuncs[0]; - var type = new NubFuncType(traitFunc.ReturnType, traitFunc.Parameters.Select(p => p.Type).ToList()); - return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); + var type = new NubFuncType(BindType(traitFunc.ReturnType), traitFunc.Parameters.Select(p => BindType(p.Type)).ToList()); + 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]; - 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()); } @@ -531,6 +528,48 @@ public sealed class Binder 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 diff --git a/src/compiler/Syntax/DefinitionTable.cs b/src/compiler/Syntax/DefinitionTable.cs index c2f3bac..421df90 100644 --- a/src/compiler/Syntax/DefinitionTable.cs +++ b/src/compiler/Syntax/DefinitionTable.cs @@ -60,4 +60,64 @@ public sealed class DefinitionTable { return trait.Functions.Where(x => x.Name == name); } +} + +public sealed class BoundDefinitionTable +{ + private readonly List _topLevelNodes; + + public BoundDefinitionTable(IEnumerable syntaxTrees) + { + _topLevelNodes = syntaxTrees.SelectMany(x => x.TopLevelNodes).ToList(); + } + + public BoundLocalFuncNode LookupLocalFunc(string @namespace, string name) + { + return _topLevelNodes + .OfType() + .First(x => x.Namespace == @namespace && x.Name == name); + } + + public BoundExternFuncNode LookupExternFunc(string @namespace, string name) + { + return _topLevelNodes + .OfType() + .First(x => x.Namespace == @namespace && x.Name == name); + } + + public BoundStructNode LookupStruct(string @namespace, string name) + { + return _topLevelNodes + .OfType() + .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() + .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() + .First(x => x.Namespace == @namespace && x.Name == name); + } + + public BoundTraitFuncNode LookupTraitFunc(BoundTraitNode trait, string name) + { + return trait.Functions.First(x => x.Name == name); + } } \ No newline at end of file diff --git a/src/compiler/Syntax/Node/Expression.cs b/src/compiler/Syntax/Node/Expression.cs index c7d3c9e..8925678 100644 --- a/src/compiler/Syntax/Node/Expression.cs +++ b/src/compiler/Syntax/Node/Expression.cs @@ -36,7 +36,9 @@ public record FuncCallNode(IEnumerable Tokens, ExpressionNode Expression, public record BoundFuncCallNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Expression, List Parameters) : BoundExpressionNode(Tokens, Type); public record IdentifierNode(IEnumerable Tokens, Optional Namespace, string Name) : ExpressionNode(Tokens); -public record BoundIdentifierNode(IEnumerable Tokens, NubType Type, Optional Namespace, string Name) : BoundExpressionNode(Tokens, Type); +public record BoundVariableIdentNode(IEnumerable Tokens, NubType Type, string Name) : BoundExpressionNode(Tokens, Type); +public record BoundLocalFuncIdentNode(IEnumerable Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type); +public record BoundExternFuncIdentNode(IEnumerable Tokens, NubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type); public record ArrayInitializerNode(IEnumerable Tokens, ExpressionNode Capacity, NubType ElementType) : ExpressionNode(Tokens); public record BoundArrayInitializerNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type); @@ -53,8 +55,10 @@ public record BoundAddressOfNode(IEnumerable Tokens, NubType Type, BoundE public record LiteralNode(IEnumerable Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens); public record BoundLiteralNode(IEnumerable Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type); -public record MemberAccessNode(IEnumerable Tokens, ExpressionNode Expression, string Member) : ExpressionNode(Tokens); -public record BoundMemberAccessNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Expression, string Member) : BoundExpressionNode(Tokens, Type); +public record MemberAccessNode(IEnumerable Tokens, ExpressionNode Target, string Member) : ExpressionNode(Tokens); +public record BoundStructFieldAccessNode(IEnumerable Tokens, NubType Type, NubStructType StructType, BoundExpressionNode Target, string Field) : BoundExpressionNode(Tokens, Type); +public record BoundTraitImplFuncAccessNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type); +public record BoundTraitFuncAccessNode(IEnumerable Tokens, NubType Type, NubTraitType TraitType, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type); public record StructInitializerNode(IEnumerable Tokens, NubType StructType, Dictionary Initializers) : ExpressionNode(Tokens); public record BoundStructInitializerNode(IEnumerable Tokens, NubType Type, NubType StructType, Dictionary Initializers) : BoundExpressionNode(Tokens, Type); diff --git a/src/compiler/Syntax/NubType.cs b/src/compiler/Syntax/NubType.cs index 52f10d1..e9a7501 100644 --- a/src/compiler/Syntax/NubType.cs +++ b/src/compiler/Syntax/NubType.cs @@ -86,6 +86,18 @@ public class NubCustomType(string @namespace, string name) : NubComplexType 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 NubType BaseType { get; } = baseType;