From 5658e0e25d63c24c3f5c12defa5105c89a641406 Mon Sep 17 00:00:00 2001 From: nub31 Date: Sun, 6 Jul 2025 22:38:00 +0200 Subject: [PATCH] ... --- src/compiler/NubLang/DefinitionTable.cs | 4 +- .../NubLang/Generation/QBE/QBEGenerator.cs | 577 ++++++++---------- src/compiler/NubLang/NubBoundType.cs | 191 ------ src/compiler/NubLang/NubType.cs | 210 +++++-- src/compiler/NubLang/Syntax/Binding/Binder.cs | 184 ++---- .../NubLang/Syntax/Node/Definition.cs | 14 +- .../NubLang/Syntax/Node/Expression.cs | 34 +- src/compiler/NubLang/Syntax/Node/Statement.cs | 2 +- 8 files changed, 503 insertions(+), 713 deletions(-) delete mode 100644 src/compiler/NubLang/NubBoundType.cs diff --git a/src/compiler/NubLang/DefinitionTable.cs b/src/compiler/NubLang/DefinitionTable.cs index 7ab652c..d7464e6 100644 --- a/src/compiler/NubLang/DefinitionTable.cs +++ b/src/compiler/NubLang/DefinitionTable.cs @@ -94,14 +94,14 @@ public sealed class BoundDefinitionTable return structNode.Fields.First(x => x.Name == field); } - public IEnumerable LookupTraitImpls(BoundNubType itemType) + public IEnumerable LookupTraitImpls(NubType itemType) { return _topLevelNodes .OfType() .Where(x => x.ForType == itemType); } - public BoundTraitFuncImplNode LookupTraitFuncImpl(BoundNubType forType, string name) + public BoundTraitFuncImplNode LookupTraitFuncImpl(NubType forType, string name) { return _topLevelNodes .OfType() diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs index f9ead92..982b798 100644 --- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -131,67 +131,139 @@ public static class QBEGenerator return $"$impl{++_implFuncNameIndex}"; } - private static string StructTypeName(BoundNubStructType structType) + private static string CustomTypeName(NubCustomType customType) { - return $":{structType.Namespace}_{structType.Name}"; + return CustomTypeName(customType.Namespace, customType.Name); } - private static string TraitTypeName(BoundNubTraitType traitType) + private static string CustomTypeName(string @namespace, string name) { - return $":{traitType.Namespace}_{traitType.Name}"; + return $":{@namespace}_{name}"; } - private static void EmitStore(BoundNubType type, string value, string destination) + private static int AlignTo(int offset, int alignment) { - var store = type switch + return (offset + alignment - 1) & ~(alignment - 1); + } + + private static int SizeOf(NubType type) + { + if (type.IsSimpleType(out var simpleType, out var complexType)) { - BoundNubComplexType => "storel", - BoundNubSimpleType simpleType => simpleType switch + return simpleType.StorageSize switch { - BoundNubFuncType or BoundNubPointerType => "loadl", - BoundNubPrimitiveType primitiveType => primitiveType.Kind 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(simpleType.StorageSize)) + }; + } + + // Only custom types such as structs/traits have known sizes for now. For objects other than custom types, we store pointers + if (complexType is not NubCustomType customType) + { + return 8; + } + + switch (customType.Kind(_definitionTable)) + { + case CustomTypeKind.Struct: + { + var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name); + var size = 0; + var maxAlignment = 1; + + foreach (var field in structDef.Fields) { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "storel", - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "storew", - PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => "storeh", - PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "storeb", - PrimitiveTypeKind.F64 => "stored", - PrimitiveTypeKind.F32 => "stores", - _ => throw new ArgumentOutOfRangeException() - }, - _ => throw new ArgumentOutOfRangeException($"'{type}' type cannot be used in store instructions") - }, - _ => throw new UnreachableException() - }; + var fieldAlignment = field.Type.Alignment(_definitionTable); + maxAlignment = Math.Max(maxAlignment, fieldAlignment); + + size = AlignTo(size, fieldAlignment); + size += SizeOf(field.Type); + } + + return AlignTo(size, maxAlignment); + } + case CustomTypeKind.Trait: + { + return 16; + } + default: + throw new ArgumentOutOfRangeException(); + } + } + + private static int OffsetOf(BoundStructNode structDefinition, string member) + { + var offset = 0; + + foreach (var field in structDefinition.Fields) + { + if (field.Name == member) + { + return offset; + } + + var fieldAlignment = field.Type.Alignment(_definitionTable); + + offset = AlignTo(offset, fieldAlignment); + offset += SizeOf(field.Type); + } + + throw new UnreachableException($"Member '{member}' not found in struct"); + } + + private static void EmitStore(NubType type, string value, string destination) + { + string store; + + if (type.IsSimpleType(out var simpleType, out _)) + { + store = simpleType.StorageSize switch + { + StorageSize.I8 or StorageSize.U8 => "storeb", + StorageSize.I16 or StorageSize.U16 => "storeh", + StorageSize.I32 or StorageSize.U32 => "storew", + StorageSize.I64 or StorageSize.U64 => "storel", + StorageSize.F32 => "stores", + StorageSize.F64 => "stored", + _ => throw new ArgumentOutOfRangeException(nameof(simpleType.StorageSize)) + }; + } + else + { + store = "storel"; + } _writer.Indented($"{store} {value}, {destination}"); } - private static Val EmitLoad(BoundNubType type, string from) + private static Val EmitLoad(NubType type, string from) { - var into = TmpName(); - var load = type switch + string load; + + if (type.IsSimpleType(out var simpleType, out _)) { - BoundNubComplexType => "loadl", - BoundNubSimpleType simpleType => simpleType switch + load = simpleType.StorageSize switch { - BoundNubFuncType or BoundNubPointerType => "loadl", - BoundNubPrimitiveType primitiveType => primitiveType.Kind switch - { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "loadl", - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "loadw", - PrimitiveTypeKind.I16 => "loadsh", - PrimitiveTypeKind.I8 => "loadsb", - PrimitiveTypeKind.U16 => "loaduh", - PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "loadub", - PrimitiveTypeKind.F64 => "loadd", - PrimitiveTypeKind.F32 => "loads", - _ => throw new ArgumentOutOfRangeException() - }, - _ => throw new ArgumentOutOfRangeException($"'{type}' type cannot be used in load instructions") - }, - _ => throw new UnreachableException() - }; + StorageSize.I64 or StorageSize.U64 => "loadl", + StorageSize.I32 or StorageSize.U32 => "loadw", + StorageSize.I16 => "loadsh", + StorageSize.I8 => "loadsb", + StorageSize.U16 => "loaduh", + StorageSize.U8 => "loadub", + StorageSize.F64 => "loadd", + StorageSize.F32 => "loads", + _ => throw new ArgumentOutOfRangeException(nameof(simpleType.StorageSize)) + }; + } + else + { + load = "loadl"; + } + + var into = TmpName(); _writer.Indented($"{into} {QBEAssign(type)} {load} {from}"); @@ -203,7 +275,7 @@ public static class QBEGenerator _writer.Indented($"call $nub_memcpy(l {source}, l {destination}, l {length})"); } - private static string EmitArraySizeInBytes(BoundNubArrayType type, string array) + private static string EmitArraySizeInBytes(NubArrayType type, string array) { var size = TmpName(); _writer.Indented($"{size} =l loadl {array}"); @@ -265,52 +337,30 @@ public static class QBEGenerator var value = EmitUnwrap(EmitExpression(source)); - switch (source.Type) + if (source.Type.IsSimpleType(out var simpleType, out var complexType)) { - case BoundNubComplexType complexType: + EmitStore(simpleType, value, destinationPointer); + } + else + { + if (complexType is NubCustomType customType) + { + EmitMemcpy(value, destinationPointer, SizeOf(customType).ToString()); + } + else { var size = complexType switch { - BoundNubArrayType arrayType => EmitArraySizeInBytes(arrayType, value), - BoundNubCStringType => EmitCStringSizeInBytes(value), - BoundNubStringType => EmitStringSizeInBytes(value), - BoundNubStructType structType => SizeOf(structType).ToString(), - BoundNubTraitType traitType => SizeOf(traitType).ToString(), - _ => throw new ArgumentOutOfRangeException(nameof(complexType)) + NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value), + NubCStringType => EmitCStringSizeInBytes(value), + NubStringType => EmitStringSizeInBytes(value), + _ => throw new ArgumentOutOfRangeException(nameof(source.Type)) }; - switch (complexType) - { - case BoundNubArrayType: - case BoundNubCStringType: - case BoundNubStringType: - { - var buffer = TmpName(); - _writer.Indented($"{buffer} =l alloc8 {size}"); - EmitMemcpy(value, buffer, size); - EmitStore(source.Type, buffer, destinationPointer); - return; - } - case BoundNubStructType: - case BoundNubTraitType: - { - EmitMemcpy(value, destinationPointer, size); - return; - } - default: - { - throw new ArgumentOutOfRangeException(nameof(complexType)); - } - } - } - case BoundNubSimpleType simpleType: - { - EmitStore(simpleType, value, destinationPointer); - return; - } - default: - { - throw new ArgumentOutOfRangeException(nameof(source.Type)); + var buffer = TmpName(); + _writer.Indented($"{buffer} =l alloc8 {size}"); + EmitMemcpy(value, buffer, size); + EmitStore(complexType, buffer, destinationPointer); } } } @@ -342,46 +392,36 @@ public static class QBEGenerator var value = EmitUnwrap(EmitExpression(source)); - switch (source.Type) + if (source.Type.IsSimpleType(out _, out var complexType)) { - case BoundNubComplexType complexType: - { - var destination = TmpName(); - - var size = complexType switch - { - BoundNubArrayType arrayType => EmitArraySizeInBytes(arrayType, value), - BoundNubCStringType => EmitCStringSizeInBytes(value), - BoundNubStringType => EmitStringSizeInBytes(value), - BoundNubStructType structType => SizeOf(structType).ToString(), - BoundNubTraitType traitType => SizeOf(traitType).ToString(), - _ => throw new ArgumentOutOfRangeException(nameof(complexType)) - }; - - _writer.Indented($"{destination} =l alloc8 {size}"); - EmitMemcpy(value, destination, size); - return destination; - } - case BoundNubSimpleType: - { - return value; - } - default: - { - throw new ArgumentOutOfRangeException(nameof(source.Type)); - } + // Simple types are passed in registers and are therefore always copied + return value; } + + var size = complexType switch + { + NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value), + NubCStringType => EmitCStringSizeInBytes(value), + NubStringType => EmitStringSizeInBytes(value), + NubCustomType customType => SizeOf(customType).ToString(), + _ => throw new ArgumentOutOfRangeException(nameof(source.Type)) + }; + + var destination = TmpName(); + _writer.Indented($"{destination} =l alloc8 {size}"); + EmitMemcpy(value, destination, size); + return destination; } - private static string QBEAssign(BoundNubType type) + private static string QBEAssign(NubType type) { return type switch { - BoundNubComplexType => "=l", - BoundNubSimpleType simpleType => simpleType switch + NubComplexType => "=l", + NubSimpleType simpleType => simpleType switch { - BoundNubFuncType or BoundNubFuncType => "=l", - BoundNubPrimitiveType primitiveType => primitiveType.Kind switch + NubFuncType or NubFuncType => "=l", + NubPrimitiveType primitiveType => primitiveType.Kind switch { PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "=l", PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "=w", @@ -397,139 +437,34 @@ public static class QBEGenerator }; } - private static int AlignmentOf(BoundNubType type) + // Utility to create QBE type names for function parameters and return types + private static string FuncQBETypeName(NubType type) { - switch (type) + if (type.IsSimpleType(out var simpleType, out var complexType)) { - case BoundNubPrimitiveType primitiveType: + return simpleType.StorageSize switch { - return primitiveType.Kind switch - { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 or PrimitiveTypeKind.F64 => 8, - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.F32 => 4, - PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => 2, - PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => 1, - _ => throw new ArgumentOutOfRangeException() - }; - } - case BoundNubStructType structType: - { - var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name); - return structDef.Fields.Max(f => AlignmentOf(f.Type)); - } - case BoundNubTraitType: - case BoundNubPointerType: - case BoundNubArrayType: - case BoundNubCStringType: - case BoundNubStringType: - case BoundNubFuncType: - return 8; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private static int AlignTo(int offset, int alignment) - { - return (offset + alignment - 1) & ~(alignment - 1); - } - - private static int SizeOf(BoundNubType type) - { - switch (type) - { - case BoundNubPrimitiveType primitiveType: - { - return primitiveType.Kind switch - { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 or PrimitiveTypeKind.F64 => 8, - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.F32 => 4, - PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => 2, - PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => 1, - _ => throw new ArgumentOutOfRangeException() - }; - } - case BoundNubStructType structType: - { - var structDef = _definitionTable.LookupStruct(structType.Namespace, structType.Name); - var size = 0; - var maxAlignment = 1; - - foreach (var field in structDef.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; - } - case BoundNubTraitType: - return 16; - case BoundNubPointerType: - case BoundNubArrayType: - case BoundNubCStringType: - case BoundNubStringType: - case BoundNubFuncType: - return 8; - default: - throw new ArgumentOutOfRangeException(); - } - } - - private static int OffsetOf(BoundStructNode structDefinition, string member) - { - var offset = 0; - - foreach (var field in structDefinition.Fields) - { - if (field.Name == member) - { - return offset; - } - - var fieldAlignment = AlignmentOf(field.Type); - - offset = AlignTo(offset, fieldAlignment); - offset += SizeOf(field.Type); + StorageSize.I64 or StorageSize.U64 => "l", + StorageSize.I32 or StorageSize.U32 => "w", + StorageSize.I16 => "sh", + StorageSize.I8 => "sb", + StorageSize.U16 => "uh", + StorageSize.U8 => "ub", + StorageSize.F64 => "d", + StorageSize.F32 => "s", + _ => throw new ArgumentOutOfRangeException() + }; } - throw new UnreachableException($"Member '{member}' not found in struct"); - } - - private static string FuncQBETypeName(BoundNubType type) - { - return type switch + if (complexType is NubCustomType customType) { - BoundNubStructType structType => StructTypeName(structType), - BoundNubTraitType traitType => TraitTypeName(traitType), - BoundNubComplexType => "l", - BoundNubSimpleType simpleType => simpleType switch - { - BoundNubPointerType or BoundNubFuncType => "l", - BoundNubPrimitiveType primitiveType => primitiveType.Kind switch - { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", - PrimitiveTypeKind.I16 => "sh", - PrimitiveTypeKind.I8 => "sb", - PrimitiveTypeKind.U16 => "uh", - PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "ub", - PrimitiveTypeKind.F64 => "d", - PrimitiveTypeKind.F32 => "s", - _ => throw new ArgumentOutOfRangeException() - }, - _ => throw new NotSupportedException($"'{type}' type cannot be used as a function definition type") - }, - _ => throw new UnreachableException() - }; + return CustomTypeName(customType); + } + + return "l"; } - private static void EmitFuncDefinition(BoundNode debugNode, string name, List parameters, BoundNubType returnType, BoundBlock body, bool exported) + private static void EmitFuncDefinition(BoundNode debugNode, string name, List parameters, NubType returnType, BoundBlock body, bool exported) { _variables.Clear(); _variableScopes.Clear(); @@ -544,7 +479,7 @@ public static class QBEGenerator } builder.Append("function "); - if (returnType is not BoundNubVoidType) + if (returnType is not NubVoidType) { builder.Append(FuncQBETypeName(returnType) + ' '); } @@ -564,7 +499,7 @@ public static class QBEGenerator if (body.Statements.LastOrDefault() is not BoundReturnNode) { - if (returnType is BoundNubVoidType) + if (returnType is NubVoidType) { _writer.Indented("ret"); } @@ -575,7 +510,7 @@ public static class QBEGenerator private static void EmitStructDefinition(BoundStructNode structDef) { - _writer.WriteLine($"type {StructTypeName(new BoundNubStructType(structDef.Namespace, structDef.Name))} = {{ "); + _writer.WriteLine($"type {CustomTypeName(structDef.Namespace, structDef.Name)} = {{ "); var types = new Dictionary(); @@ -596,34 +531,32 @@ public static class QBEGenerator string StructDefQBEType(BoundStructFieldNode field) { - return field.Type switch + if (field.Type.IsSimpleType(out var simpleType, out var complexType)) { - BoundNubStructType structType => StructTypeName(structType), - BoundNubTraitType traitType => TraitTypeName(traitType), - BoundNubComplexType => "l", - BoundNubSimpleType simpleType => simpleType switch + return simpleType.StorageSize switch { - BoundNubPointerType or BoundNubFuncType => "l", - BoundNubPrimitiveType primitiveType => primitiveType.Kind switch - { - PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => "l", - PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 => "w", - PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => "h", - PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.Bool => "b", - PrimitiveTypeKind.F64 => "d", - PrimitiveTypeKind.F32 => "s", - _ => throw new ArgumentOutOfRangeException() - }, - _ => throw new NotSupportedException($"'{field.Type}' type cannot be used in structs") - }, - _ => throw new UnreachableException() - }; + StorageSize.I64 or StorageSize.U64 => "l", + StorageSize.I32 or StorageSize.U32 => "w", + StorageSize.I16 or StorageSize.U16 => "h", + StorageSize.I8 or StorageSize.U8 => "b", + StorageSize.F64 => "d", + StorageSize.F32 => "s", + _ => throw new ArgumentOutOfRangeException() + }; + } + + if (complexType is NubCustomType customType) + { + return CustomTypeName(customType); + } + + return "l"; } } private static void EmitTraitVTable(BoundTraitNode traitDef) { - _writer.WriteLine($"type {TraitTypeName(new BoundNubTraitType(traitDef.Namespace, traitDef.Name))} = {{"); + _writer.WriteLine($"type {CustomTypeName(traitDef.Namespace, traitDef.Name)} = {{"); foreach (var func in traitDef.Functions) { @@ -643,10 +576,10 @@ public static class QBEGenerator EmitAssignment(assignment); break; case BoundBreakNode @break: - EmitBreak(@break); + EmitBreak(); break; case BoundContinueNode @continue: - EmitContinue(@continue); + EmitContinue(); break; case BoundIfNode ifStatement: EmitIf(ifStatement); @@ -700,13 +633,13 @@ public static class QBEGenerator _codeIsReachable = true; } - private static void EmitBreak(BoundBreakNode @break) + private static void EmitBreak() { _writer.Indented($"jmp {_breakLabels.Peek()}"); _codeIsReachable = false; } - private static void EmitContinue(BoundContinueNode @continue) + private static void EmitContinue() { _writer.Indented($"jmp {_continueLabels.Peek()}"); _codeIsReachable = false; @@ -821,7 +754,7 @@ public static class QBEGenerator var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target)); var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index)); - var elementType = ((BoundNubArrayType)arrayIndexAccess.Target.Type).ElementType; + var elementType = ((NubArrayType)arrayIndexAccess.Target.Type).ElementType; var pointer = TmpName(); _writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}"); @@ -900,7 +833,7 @@ public static class QBEGenerator return new Val(outputName, binaryExpression.Type, ValKind.Direct); } - private static string EmitBinaryInstructionFor(BinaryExpressionOperator op, BoundNubType type, string left, string right) + private static string EmitBinaryInstructionFor(BinaryExpressionOperator op, NubType type, string left, string right) { if (op is BinaryExpressionOperator.Equal or @@ -912,47 +845,41 @@ public static class QBEGenerator { char suffix; - if (type.Is8BitInteger) + if (!type.IsSimpleType(out var simpleType, out _)) { - if (type.IsSignedInteger) - { + throw new NotSupportedException("Binary operations is only supported for simple types."); + } + + switch (simpleType.StorageSize) + { + case StorageSize.I8: _writer.Indented($"{left} =w extsb {left}"); _writer.Indented($"{right} =w extsb {right}"); - } - else - { + suffix = 'w'; + break; + case StorageSize.U8: _writer.Indented($"{left} =w extub {left}"); _writer.Indented($"{right} =w extub {right}"); - } - - suffix = 'w'; - } - else if (type.Is16BitInteger) - { - if (type.IsSignedInteger) - { + suffix = 'w'; + break; + case StorageSize.I16: _writer.Indented($"{left} =w extsh {left}"); _writer.Indented($"{right} =w extsh {right}"); - } - else - { + suffix = 'w'; + break; + case StorageSize.U16: _writer.Indented($"{left} =w extuh {left}"); _writer.Indented($"{right} =w extuh {right}"); - } - - suffix = 'w'; - } - else if (type.Is32BitInteger) - { - suffix = 'w'; - } - else if (type.Is64BitInteger) - { - suffix = 'l'; - } - else - { - throw new NotSupportedException($"Unsupported type '{type}' for binary operator '{op}'"); + suffix = 'w'; + break; + case StorageSize.I32 or StorageSize.U32: + suffix = 'w'; + break; + case StorageSize.I64 or StorageSize.U64: + suffix = 'l'; + break; + default: + throw new NotSupportedException($"Unsupported type '{simpleType}' for binary operator '{op}'"); } if (op is BinaryExpressionOperator.Equal) @@ -967,18 +894,14 @@ public static class QBEGenerator string sign; - if (type.IsSignedInteger) + if (simpleType is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.I64 }) { sign = "s"; } - else if (type.IsUnsignedInteger) + else if (simpleType is NubPrimitiveType { Kind: PrimitiveTypeKind.U8 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.U64 }) { sign = "u"; } - else if (type.IsFloat) - { - sign = ""; - } else { throw new NotSupportedException($"Unsupported type '{type}' for binary operator '{op}'"); @@ -1027,21 +950,21 @@ public static class QBEGenerator { case LiteralKind.Integer: { - if (literal.Type.IsFloat32) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }) { var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture); var bits = BitConverter.SingleToInt32Bits(value); return new Val(bits.ToString(), literal.Type, ValKind.Direct); } - if (literal.Type.IsFloat64) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }) { var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture); var bits = BitConverter.DoubleToInt64Bits(value); return new Val(bits.ToString(), literal.Type, ValKind.Direct); } - if (literal.Type.IsInteger) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 }) { return new Val(literal.Literal, literal.Type, ValKind.Direct); } @@ -1050,19 +973,19 @@ public static class QBEGenerator } case LiteralKind.Float: { - if (literal.Type.IsInteger) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 }) { return new Val(literal.Literal.Split(".").First(), literal.Type, ValKind.Direct); } - if (literal.Type.IsFloat32) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }) { var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture); var bits = BitConverter.SingleToInt32Bits(value); return new Val(bits.ToString(), literal.Type, ValKind.Direct); } - if (literal.Type.IsFloat64) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }) { var value = double.Parse(literal.Literal, CultureInfo.InvariantCulture); var bits = BitConverter.DoubleToInt64Bits(value); @@ -1073,14 +996,14 @@ public static class QBEGenerator } case LiteralKind.String: { - if (literal.Type.IsString) + if (literal.Type is NubStringType) { var stringLiteral = new StringLiteral(literal.Literal, StringName()); _stringLiterals.Add(stringLiteral); return new Val(stringLiteral.Name, literal.Type, ValKind.Direct); } - if (literal.Type.IsCString) + if (literal.Type is NubCStringType) { var cStringLiteral = new CStringLiteral(literal.Literal, CStringName()); _cStringLiterals.Add(cStringLiteral); @@ -1091,7 +1014,7 @@ public static class QBEGenerator } case LiteralKind.Bool: { - if (literal.Type.IsBool) + if (literal.Type is NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }) { return new Val(bool.Parse(literal.Literal) ? "1" : "0", literal.Type, ValKind.Direct); } @@ -1142,16 +1065,16 @@ public static class QBEGenerator { switch (unaryExpression.Operand.Type) { - case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I64 }: + case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }: _writer.Indented($"{outputName} =l neg {operand}"); return new Val(outputName, unaryExpression.Type, ValKind.Direct); - case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }: + case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I8 }: _writer.Indented($"{outputName} =w neg {operand}"); return new Val(outputName, unaryExpression.Type, ValKind.Direct); - case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F64 }: + case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }: _writer.Indented($"{outputName} =d neg {operand}"); return new Val(outputName, unaryExpression.Type, ValKind.Direct); - case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F32 }: + case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }: _writer.Indented($"{outputName} =s neg {operand}"); return new Val(outputName, unaryExpression.Type, ValKind.Direct); } @@ -1162,7 +1085,7 @@ public static class QBEGenerator { switch (unaryExpression.Operand.Type) { - case BoundNubPrimitiveType { Kind: PrimitiveTypeKind.Bool }: + case NubPrimitiveType { Kind: PrimitiveTypeKind.Bool }: _writer.Indented($"{outputName} =w xor {operand}, 1"); return new Val(outputName, unaryExpression.Type, ValKind.Direct); } @@ -1189,7 +1112,7 @@ public static class QBEGenerator _writer.Indented($"{output} =l add {target}, {offset}"); // If the accessed member is an inline struct, it will not be a pointer - if (structFieldAccess.Type is BoundNubStructType) + if (structFieldAccess.Type is NubCustomType customType && customType.Kind(_definitionTable) == CustomTypeKind.Struct) { return new Val(output, structFieldAccess.Type, ValKind.Direct); } @@ -1232,7 +1155,7 @@ public static class QBEGenerator parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}"); } - if (funcCall.Type.IsVoid) + if (funcCall.Type is NubVoidType) { _writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})"); return new Val(string.Empty, funcCall.Type, ValKind.Direct); @@ -1274,7 +1197,7 @@ internal class Variable(string name, Val val) public Val Val { get; } = val; } -internal record Val(string Name, BoundNubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null); +internal record Val(string Name, NubType Type, ValKind Kind, MethodCallContext? FuncCallContext = null); internal record MethodCallContext(Val ThisArg); diff --git a/src/compiler/NubLang/NubBoundType.cs b/src/compiler/NubLang/NubBoundType.cs deleted file mode 100644 index 1345286..0000000 --- a/src/compiler/NubLang/NubBoundType.cs +++ /dev/null @@ -1,191 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace NubLang; - -public abstract class BoundNubType : IEquatable -{ - public bool Is8BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 }; - public bool Is16BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 }; - public bool Is32BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 }; - public bool Is64BitInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 }; - - public bool IsSignedInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.I64 }; - public bool IsUnsignedInteger => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.U8 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.U64 }; - public bool IsInteger => IsSignedInteger || IsUnsignedInteger; - - public bool IsFloat32 => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F32 }; - public bool IsFloat64 => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.F64 }; - public bool IsFloat => IsFloat32 || IsFloat64; - - public bool IsNumber => IsFloat || IsInteger; - - public bool IsVoid => this is BoundNubVoidType; - public bool IsString => this is BoundNubStringType; - public bool IsCString => this is BoundNubCStringType; - public bool IsBool => this is BoundNubPrimitiveType { Kind: PrimitiveTypeKind.Bool }; - - public override bool Equals(object? obj) => obj is BoundNubType other && Equals(other); - - public abstract bool Equals(BoundNubType? other); - public abstract override int GetHashCode(); - public abstract override string ToString(); - - public static bool operator ==(BoundNubType? left, BoundNubType? right) => Equals(left, right); - public static bool operator !=(BoundNubType? left, BoundNubType? right) => !Equals(left, right); -} - -public abstract class BoundNubComplexType : BoundNubType; - -public abstract class BoundNubSimpleType : BoundNubType; - -public class BoundNubCStringType : BoundNubComplexType -{ - public override string ToString() => "cstring"; - public override bool Equals(BoundNubType? other) => other is BoundNubCStringType; - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubCStringType)); -} - -public class BoundNubStringType : BoundNubComplexType -{ - public override string ToString() => "string"; - public override bool Equals(BoundNubType? other) => other is BoundNubStringType; - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubStringType)); -} - -public class BoundNubFuncType(BoundNubType returnType, List parameters) : BoundNubSimpleType -{ - public BoundNubType ReturnType { get; } = returnType; - public List Parameters { get; } = parameters; - - public override string ToString() => $"func({string.Join(", ", Parameters)}): {ReturnType}"; - - public override bool Equals(BoundNubType? other) => other is BoundNubFuncType func && ReturnType.Equals(func.ReturnType) && Parameters.SequenceEqual(func.Parameters); - - public override int GetHashCode() - { - var hash = new HashCode(); - hash.Add(typeof(BoundNubFuncType)); - hash.Add(ReturnType); - foreach (var param in Parameters) - { - hash.Add(param); - } - - return hash.ToHashCode(); - } -} - -public class BoundNubStructType(string @namespace, string name) : BoundNubComplexType -{ - public string Namespace { get; } = @namespace; - public string Name { get; } = name; - - public override string ToString() => $"{Namespace}::{Name}"; - - public override bool Equals(BoundNubType? other) => other is BoundNubStructType custom && Namespace == custom.Namespace && Name == custom.Name; - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubStructType), Namespace, Name); -} - -public class BoundNubTraitType(string @namespace, string name) : BoundNubComplexType -{ - public string Namespace { get; } = @namespace; - public string Name { get; } = name; - - public override string ToString() => $"{Namespace}::{Name}"; - - public override bool Equals(BoundNubType? other) => other is BoundNubTraitType custom && Namespace == custom.Namespace && Name == custom.Name; - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubTraitType), Namespace, Name); -} - -public class BoundNubPointerType(BoundNubType baseType) : BoundNubSimpleType -{ - public BoundNubType BaseType { get; } = baseType; - - public override string ToString() => "^" + BaseType; - - public override bool Equals(BoundNubType? other) => other is BoundNubPointerType pointer && BaseType.Equals(pointer.BaseType); - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubPointerType), BaseType); -} - -public class BoundNubArrayType(BoundNubType elementType) : BoundNubComplexType -{ - public BoundNubType ElementType { get; } = elementType; - - public override string ToString() => "[]" + ElementType; - - public override bool Equals(BoundNubType? other) => other is BoundNubArrayType array && ElementType.Equals(array.ElementType); - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubArrayType), ElementType); -} - -public class BoundNubVoidType : BoundNubSimpleType -{ - public override string ToString() => "void"; - public override bool Equals(BoundNubType? other) => other is BoundNubVoidType; - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubVoidType)); -} - -public class BoundNubPrimitiveType(PrimitiveTypeKind kind) : BoundNubSimpleType -{ - public PrimitiveTypeKind Kind { get; } = kind; - - public static BoundNubPrimitiveType I64 => new(PrimitiveTypeKind.I64); - public static BoundNubPrimitiveType I32 => new(PrimitiveTypeKind.I32); - public static BoundNubPrimitiveType I16 => new(PrimitiveTypeKind.I16); - public static BoundNubPrimitiveType I8 => new(PrimitiveTypeKind.I8); - - public static BoundNubPrimitiveType U64 => new(PrimitiveTypeKind.U64); - public static BoundNubPrimitiveType U32 => new(PrimitiveTypeKind.U32); - public static BoundNubPrimitiveType U16 => new(PrimitiveTypeKind.U16); - public static BoundNubPrimitiveType U8 => new(PrimitiveTypeKind.U8); - - public static BoundNubPrimitiveType F64 => new(PrimitiveTypeKind.F64); - public static BoundNubPrimitiveType F32 => new(PrimitiveTypeKind.F32); - - public static BoundNubPrimitiveType Bool => new(PrimitiveTypeKind.Bool); - - public static bool TryParse(string s, [NotNullWhen(true)] out PrimitiveTypeKind? kind) - { - kind = s switch - { - "i64" => PrimitiveTypeKind.I64, - "i32" => PrimitiveTypeKind.I32, - "i16" => PrimitiveTypeKind.I16, - "i8" => PrimitiveTypeKind.I8, - "u64" => PrimitiveTypeKind.U64, - "u32" => PrimitiveTypeKind.U32, - "u16" => PrimitiveTypeKind.U16, - "u8" => PrimitiveTypeKind.U8, - "f64" => PrimitiveTypeKind.F64, - "f32" => PrimitiveTypeKind.F32, - "bool" => PrimitiveTypeKind.Bool, - _ => null - }; - - return kind != null; - } - - 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(BoundNubType? other) => other is BoundNubPrimitiveType primitive && primitive.Kind == Kind; - public override int GetHashCode() => HashCode.Combine(typeof(BoundNubPrimitiveType), Kind.GetHashCode()); -} \ No newline at end of file diff --git a/src/compiler/NubLang/NubType.cs b/src/compiler/NubLang/NubType.cs index fcdc3f6..fb686ef 100644 --- a/src/compiler/NubLang/NubType.cs +++ b/src/compiler/NubLang/NubType.cs @@ -1,7 +1,44 @@ -namespace NubLang; +using System.Diagnostics.CodeAnalysis; + +namespace NubLang; public abstract class NubType : IEquatable { + 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, not a compex type"); + } + + public abstract int Alignment(BoundDefinitionTable definitionTable); + public override bool Equals(object? obj) => obj is NubType other && Equals(other); public abstract bool Equals(NubType? other); @@ -12,27 +49,48 @@ public abstract class NubType : IEquatable public static bool operator !=(NubType? left, NubType? right) => !Equals(left, right); } -public class NubCStringType : NubType +public enum StorageSize { - public override string ToString() => "cstring"; - public override bool Equals(NubType? other) => other is NubCStringType; - public override int GetHashCode() => HashCode.Combine(typeof(NubCStringType)); + Void, + I8, + I16, + I32, + I64, + U8, + U16, + U32, + U64, + F32, + F64 } -public class NubStringType : NubType +public abstract class NubSimpleType : NubType { - public override string ToString() => "string"; - public override bool Equals(NubType? other) => other is NubStringType; - public override int GetHashCode() => HashCode.Combine(typeof(NubStringType)); + public abstract StorageSize StorageSize { get; } + + public override int Alignment(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 class NubFuncType(NubType returnType, List parameters) : NubType +#region Simple types + +public class NubFuncType(NubType returnType, List parameters) : NubSimpleType { public NubType ReturnType { get; } = returnType; public List Parameters { get; } = parameters; - public override string ToString() => $"func({string.Join(", ", Parameters)}): {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() @@ -49,48 +107,46 @@ public class NubFuncType(NubType returnType, List parameters) : NubType } } -public class NubCustomType(string @namespace, string name) : NubType -{ - public string Namespace { get; } = @namespace; - public string Name { get; } = name; - - 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 class NubPointerType(NubType baseType) : NubType +public class NubPointerType(NubType baseType) : NubSimpleType { public NubType BaseType { get; } = baseType; - public override string ToString() => "^" + 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 NubArrayType(NubType elementType) : NubType +public class NubVoidType : NubSimpleType { - public NubType ElementType { get; } = elementType; + public override StorageSize StorageSize => StorageSize.Void; - 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); -} - -public class NubVoidType : NubType -{ 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) : NubType +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 @@ -130,4 +186,86 @@ public enum PrimitiveTypeKind F64, F32, Bool -} \ No newline at end of file +} + +#endregion + +public abstract class NubComplexType : NubType; + +#region Complex types + +public class NubCStringType : NubComplexType +{ + public override int Alignment(BoundDefinitionTable definitionTable) => 8; + + 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 Alignment(BoundDefinitionTable definitionTable) => 8; + + 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 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 Alignment(BoundDefinitionTable definitionTable) => 8; + + 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 \ No newline at end of file diff --git a/src/compiler/NubLang/Syntax/Binding/Binder.cs b/src/compiler/NubLang/Syntax/Binding/Binder.cs index 64e733e..053b188 100644 --- a/src/compiler/NubLang/Syntax/Binding/Binder.cs +++ b/src/compiler/NubLang/Syntax/Binding/Binder.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using Common; using NubLang.Diagnostics; using NubLang.Syntax.Node; @@ -14,8 +13,8 @@ public sealed class Binder private readonly DefinitionTable _definitionTable; // TODO: Implement proper variable tracking and scoping - private Dictionary _variables = new(); - private BoundNubType? _functionReturnType; + private Dictionary _variables = new(); + private NubType? _functionReturnType; public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable) { @@ -70,14 +69,14 @@ public sealed class Binder foreach (var parameter in function.Parameters) { - _variables[parameter.Name] = BindType(parameter.Type); - parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type))); + _variables[parameter.Name] = parameter.Type; + parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, parameter.Type)); } - functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, parameters, BindType(function.ReturnType), BindBlock(function.Body))); + functions.Add(new BoundTraitFuncImplNode(function.Tokens, function.Name, parameters, function.ReturnType, BindBlock(function.Body))); } - return new BoundTraitImplNode(node.Tokens, node.Namespace, BindType(node.TraitType), BindType(node.ForType), functions); + return new BoundTraitImplNode(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions); } private BoundTraitNode BindTraitDefinition(TraitNode node) @@ -90,10 +89,10 @@ public sealed class Binder foreach (var parameter in function.Parameters) { - parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type))); + parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, parameter.Type)); } - functions.Add(new BoundTraitFuncNode(node.Tokens, function.Name, parameters, BindType(function.ReturnType))); + functions.Add(new BoundTraitFuncNode(node.Tokens, function.Name, parameters, function.ReturnType)); } return new BoundTraitNode(node.Tokens, node.Namespace, node.Name, functions); @@ -109,10 +108,10 @@ public sealed class Binder if (field.Value.HasValue) { - value = BindExpression(field.Value.Value, BindType(field.Type)); + value = BindExpression(field.Value.Value, field.Type); } - structFields.Add(new BoundStructFieldNode(field.Tokens, field.Index, field.Name, BindType(field.Type), value)); + structFields.Add(new BoundStructFieldNode(field.Tokens, field.Index, field.Name, field.Type, value)); } return new BoundStructNode(node.Tokens, node.Namespace, node.Name, structFields); @@ -124,28 +123,28 @@ public sealed class Binder foreach (var parameter in node.Parameters) { - parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type))); + parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, parameter.Type)); } - return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, parameters, BindType(node.ReturnType)); + return new BoundExternFuncNode(node.Tokens, node.Namespace, node.Name, node.CallName, parameters, node.ReturnType); } private BoundLocalFuncNode BindLocalFuncDefinition(LocalFuncNode node) { _variables.Clear(); - _functionReturnType = BindType(node.ReturnType); + _functionReturnType = node.ReturnType; var parameters = new List(); foreach (var parameter in node.Parameters) { - _variables[parameter.Name] = BindType(parameter.Type); - parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type))); + _variables[parameter.Name] = parameter.Type; + parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, parameter.Type)); } var body = BindBlock(node.Body); - return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, parameters, body, BindType(node.ReturnType), node.Exported); + return new BoundLocalFuncNode(node.Tokens, node.Namespace, node.Name, parameters, body, node.ReturnType, node.Exported); } private BoundBlock BindBlock(BlockNode node) @@ -206,7 +205,7 @@ public sealed class Binder ); } - return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, BoundNubPrimitiveType.Bool), BindBlock(statement.Body), elseStatement); + return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), BindBlock(statement.Body), elseStatement); } private BoundReturnNode BindReturn(ReturnNode statement) @@ -228,11 +227,11 @@ public sealed class Binder private BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement) { - BoundNubType? type = null; + NubType? type = null; if (statement.ExplicitType.HasValue) { - type = BindType(statement.ExplicitType.Value); + type = statement.ExplicitType.Value; } var assignment = Optional.Empty(); @@ -255,10 +254,10 @@ public sealed class Binder private BoundWhileNode BindWhile(WhileNode statement) { - return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, BoundNubPrimitiveType.Bool), BindBlock(statement.Body)); + return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, new NubPrimitiveType(PrimitiveTypeKind.Bool)), BindBlock(statement.Body)); } - private BoundExpressionNode BindExpression(ExpressionNode node, BoundNubType? expectedType = null) + private BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null) { return node switch { @@ -281,7 +280,7 @@ public sealed class Binder private BoundAddressOfNode BindAddressOf(AddressOfNode expression) { var inner = BindExpression(expression.Expression); - return new BoundAddressOfNode(expression.Tokens, new BoundNubPointerType(inner.Type), inner); + return new BoundAddressOfNode(expression.Tokens, new NubPointerType(inner.Type), inner); } private BoundAnonymousFuncNode BindAnonymousFunc(AnonymousFuncNode expression) @@ -290,24 +289,24 @@ public sealed class Binder foreach (var parameter in expression.Parameters) { - parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, BindType(parameter.Type))); + parameters.Add(new BoundFuncParameterNode(parameter.Tokens, parameter.Name, parameter.Type)); } var body = BindBlock(expression.Body); - return new BoundAnonymousFuncNode(expression.Tokens, new BoundNubFuncType(BindType(expression.ReturnType), parameters.Select(x => x.Type).ToList()), parameters, body, BindType(expression.ReturnType)); + return new BoundAnonymousFuncNode(expression.Tokens, new NubFuncType(expression.ReturnType, parameters.Select(x => x.Type).ToList()), parameters, body, expression.ReturnType); } private BoundArrayIndexAccessNode BindArrayIndexAccess(ArrayIndexAccessNode expression) { var boundArray = BindExpression(expression.Target); - var elementType = ((BoundNubArrayType)boundArray.Type).ElementType; - return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, BoundNubPrimitiveType.U64)); + var elementType = ((NubArrayType)boundArray.Type).ElementType; + return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, new NubPrimitiveType(PrimitiveTypeKind.U64))); } private BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression) { - return new BoundArrayInitializerNode(expression.Tokens, new BoundNubArrayType(BindType(expression.ElementType)), BindExpression(expression.Capacity, BoundNubPrimitiveType.U64), BindType(expression.ElementType)); + return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity, new NubPrimitiveType(PrimitiveTypeKind.U64)), expression.ElementType); } private BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression) @@ -320,7 +319,7 @@ public sealed class Binder private BoundDereferenceNode BindDereference(DereferenceNode expression) { var boundExpression = BindExpression(expression.Expression); - var dereferencedType = ((BoundNubPointerType)boundExpression.Type).BaseType; + var dereferencedType = ((NubPointerType)boundExpression.Type).BaseType; return new BoundDereferenceNode(expression.Tokens, dereferencedType, boundExpression); } @@ -328,7 +327,7 @@ public sealed class Binder { var boundExpression = BindExpression(expression.Expression); - var funcType = (BoundNubFuncType)boundExpression.Type; + var funcType = (NubFuncType)boundExpression.Type; var parameters = new List(); @@ -361,7 +360,7 @@ public sealed class Binder var localFunc = localFuncs[0]; var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList()); - return new BoundLocalFuncIdentNode(expression.Tokens, BindType(type), @namespace, expression.Name); + return new BoundLocalFuncIdentNode(expression.Tokens, type, @namespace, expression.Name); } var externFuncs = _definitionTable.LookupExternFunc(@namespace, expression.Name).ToArray(); @@ -375,7 +374,7 @@ public sealed class Binder var externFunc = externFuncs[0]; var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList()); - return new BoundExternFuncIdentNode(expression.Tokens, BindType(type), @namespace, expression.Name); + return new BoundExternFuncIdentNode(expression.Tokens, type, @namespace, expression.Name); } if (!expression.Namespace.HasValue) @@ -386,14 +385,14 @@ public sealed class Binder throw new BindException(Diagnostic.Error($"No identifier with then name {(expression.Namespace.HasValue ? $"{expression.Namespace.Value}::" : "")}{expression.Name} exists").Build()); } - private BoundLiteralNode BindLiteral(LiteralNode expression, BoundNubType? expectedType = null) + private BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null) { var type = expectedType ?? expression.Kind switch { - LiteralKind.Integer => BoundNubPrimitiveType.I64, - LiteralKind.Float => BoundNubPrimitiveType.F64, - LiteralKind.String => new BoundNubStringType(), - LiteralKind.Bool => BoundNubPrimitiveType.Bool, + LiteralKind.Integer => new NubPrimitiveType(PrimitiveTypeKind.I64), + LiteralKind.Float => new NubPrimitiveType(PrimitiveTypeKind.F64), + LiteralKind.String => new NubStringType(), + LiteralKind.Bool => new NubPrimitiveType(PrimitiveTypeKind.Bool), _ => throw new ArgumentOutOfRangeException() }; @@ -404,7 +403,7 @@ public sealed class Binder { var boundExpression = BindExpression(expression.Target); - var traitFuncImpls = _definitionTable.LookupTraitFuncImpl(UnbindType(boundExpression.Type), expression.Member).ToArray(); + var traitFuncImpls = _definitionTable.LookupTraitFuncImpl(boundExpression.Type, expression.Member).ToArray(); if (traitFuncImpls.Length > 0) { if (traitFuncImpls.Length > 1) @@ -414,18 +413,18 @@ public sealed class Binder var impl = traitFuncImpls[0]; - var type = new BoundNubFuncType(BindType(impl.ReturnType), impl.Parameters.Select(p => BindType(p.Type)).ToList()); + var type = new NubFuncType(impl.ReturnType, impl.Parameters.Select(p => p.Type).ToList()); return new BoundTraitImplFuncAccessNode(expression.Tokens, type, boundExpression, expression.Member); } - if (boundExpression.Type is BoundNubTraitType traitType) + if (boundExpression.Type is NubCustomType customType) { - var traits = _definitionTable.LookupTrait(traitType.Namespace, traitType.Name).ToArray(); + var traits = _definitionTable.LookupTrait(customType.Namespace, customType.Name).ToArray(); if (traits.Length > 0) { if (traits.Length > 1) { - throw new BindException(Diagnostic.Error($"Trait {traitType.Namespace}::{traitType.Name} has multiple definitions").Build()); + throw new BindException(Diagnostic.Error($"Trait {customType.Namespace}::{customType.Name} has multiple definitions").Build()); } var trait = traits[0]; @@ -440,20 +439,17 @@ public sealed class Binder var traitFunc = traitFuncs[0]; - var type = new BoundNubFuncType(BindType(traitFunc.ReturnType), traitFunc.Parameters.Select(p => BindType(p.Type)).ToList()); - return new BoundTraitFuncAccessNode(expression.Tokens, type, traitType, boundExpression, expression.Member); + var type = new NubFuncType(traitFunc.ReturnType, traitFunc.Parameters.Select(p => p.Type).ToList()); + return new BoundTraitFuncAccessNode(expression.Tokens, type, customType, boundExpression, expression.Member); } } - } - if (boundExpression.Type is BoundNubStructType structType) - { - var structs = _definitionTable.LookupStruct(structType.Namespace, structType.Name).ToArray(); + var structs = _definitionTable.LookupStruct(customType.Namespace, customType.Name).ToArray(); if (structs.Length > 0) { if (structs.Length > 1) { - throw new BindException(Diagnostic.Error($"Struct {structType.Namespace}::{structType.Name} has multiple definitions").Build()); + throw new BindException(Diagnostic.Error($"Struct {customType.Namespace}::{customType.Name} has multiple definitions").Build()); } var @struct = structs[0]; @@ -468,7 +464,7 @@ public sealed class Binder var field = fields[0]; - return new BoundStructFieldAccessNode(expression.Tokens, BindType(field.Type), structType, boundExpression, expression.Member); + return new BoundStructFieldAccessNode(expression.Tokens, field.Type, customType, boundExpression, expression.Member); } } } @@ -513,23 +509,23 @@ public sealed class Binder throw new BindException(Diagnostic.Error($"Struct {@struct.Namespace}::{@struct.Name} has multiple fields with the name {field}").Build()); } - initializers[field] = BindExpression(initializer, BindType(fields[0].Type)); + initializers[field] = BindExpression(initializer, fields[0].Type); } - return new BoundStructInitializerNode(expression.Tokens, BindType(structType), new BoundNubStructType(@struct.Namespace, @struct.Name), initializers); + return new BoundStructInitializerNode(expression.Tokens, structType, new NubCustomType(@struct.Namespace, @struct.Name), initializers); } private BoundUnaryExpressionNode BindUnaryExpression(Node_UnaryExpressionNode expression) { var boundOperand = BindExpression(expression.Operand); - BoundNubType? type = null; + NubType? type = null; switch (expression.Operator) { case UnaryExpressionOperator.Negate: { - boundOperand = BindExpression(expression.Operand, BoundNubPrimitiveType.I64); + boundOperand = BindExpression(expression.Operand, new NubPrimitiveType(PrimitiveTypeKind.I64)); if (boundOperand.Type.IsNumber) { @@ -540,9 +536,9 @@ public sealed class Binder } case UnaryExpressionOperator.Invert: { - boundOperand = BindExpression(expression.Operand, BoundNubPrimitiveType.Bool); + boundOperand = BindExpression(expression.Operand, new NubPrimitiveType(PrimitiveTypeKind.Bool)); - type = new BoundNubPrimitiveType(PrimitiveTypeKind.Bool); + type = new NubPrimitiveType(PrimitiveTypeKind.Bool); break; } } @@ -554,82 +550,6 @@ public sealed class Binder return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand); } - - private BoundNubType BindType(NubType type) - { - switch (type) - { - case 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 BoundNubStructType(customType.Namespace, customType.Name); - } - - if (traits.Length == 1) - { - return new BoundNubTraitType(customType.Namespace, customType.Name); - } - - throw new UnreachableException(); - } - case NubArrayType arrayType: - return new BoundNubArrayType(BindType(arrayType.ElementType)); - case NubCStringType: - return new BoundNubCStringType(); - case NubStringType: - return new BoundNubStringType(); - case NubFuncType funcType: - return new BoundNubFuncType(BindType(funcType.ReturnType), funcType.Parameters.Select(BindType).ToList()); - case NubPointerType pointerType: - return new BoundNubPointerType(BindType(pointerType.BaseType)); - case NubPrimitiveType primitiveType: - return new BoundNubPrimitiveType(primitiveType.Kind); - case NubVoidType: - return new BoundNubVoidType(); - default: - throw new ArgumentOutOfRangeException(nameof(type)); - } - } - - private NubType UnbindType(BoundNubType type) - { - return type switch - { - BoundNubArrayType arrayType => new NubArrayType(UnbindType(arrayType.ElementType)), - BoundNubCStringType => new NubCStringType(), - BoundNubStringType => new NubStringType(), - BoundNubStructType structType => new NubCustomType(structType.Namespace, structType.Name), - BoundNubTraitType traitType => new NubCustomType(traitType.Namespace, traitType.Name), - BoundNubFuncType funcType => new NubFuncType(UnbindType(funcType.ReturnType), funcType.Parameters.Select(UnbindType).ToList()), - BoundNubPointerType pointerType => new NubPointerType(UnbindType(pointerType.BaseType)), - BoundNubPrimitiveType primitiveType => new NubPrimitiveType(primitiveType.Kind), - BoundNubVoidType => new NubVoidType(), - _ => throw new ArgumentOutOfRangeException(nameof(type)) - }; - } } public class BindException : Exception diff --git a/src/compiler/NubLang/Syntax/Node/Definition.cs b/src/compiler/NubLang/Syntax/Node/Definition.cs index 6995627..4b2ab24 100644 --- a/src/compiler/NubLang/Syntax/Node/Definition.cs +++ b/src/compiler/NubLang/Syntax/Node/Definition.cs @@ -4,7 +4,7 @@ using NubLang.Syntax.Tokenization; namespace NubLang.Syntax.Node; public record FuncParameterNode(IEnumerable Tokens, string Name, NubType Type) : DefinitionNode(Tokens); -public record BoundFuncParameterNode(IEnumerable Tokens, string Name, BoundNubType Type) : DefinitionNode(Tokens); +public record BoundFuncParameterNode(IEnumerable Tokens, string Name, NubType Type) : DefinitionNode(Tokens); public abstract record TopLevelNode(IEnumerable Tokens, string Namespace) : Node(Tokens); public abstract record BoundTopLevelNode(IEnumerable Tokens, string Namespace) : BoundNode(Tokens); @@ -13,25 +13,25 @@ public abstract record DefinitionNode(IEnumerable Tokens) : Node(Tokens); public abstract record BoundDefinitionNode(IEnumerable Tokens) : BoundNode(Tokens); public record LocalFuncNode(IEnumerable Tokens, string Namespace, string Name, List Parameters, BlockNode Body, NubType ReturnType, bool Exported) : TopLevelNode(Tokens, Namespace); -public record BoundLocalFuncNode(IEnumerable Tokens, string Namespace, string Name, List Parameters, BoundBlock Body, BoundNubType ReturnType, bool Exported) : BoundTopLevelNode(Tokens, Namespace); +public record BoundLocalFuncNode(IEnumerable Tokens, string Namespace, string Name, List Parameters, BoundBlock Body, NubType ReturnType, bool Exported) : BoundTopLevelNode(Tokens, Namespace); public record ExternFuncNode(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, NubType ReturnType) : TopLevelNode(Tokens, Namespace); -public record BoundExternFuncNode(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, BoundNubType ReturnType) : BoundTopLevelNode(Tokens, Namespace); +public record BoundExternFuncNode(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, NubType ReturnType) : BoundTopLevelNode(Tokens, Namespace); public record StructFieldNode(IEnumerable Tokens, int Index, string Name, NubType Type, Optional Value) : DefinitionNode(Tokens); public record StructNode(IEnumerable Tokens, string Namespace, string Name, List Fields) : TopLevelNode(Tokens, Namespace); -public record BoundStructFieldNode(IEnumerable Tokens, int Index, string Name, BoundNubType Type, Optional Value) : BoundDefinitionNode(Tokens); +public record BoundStructFieldNode(IEnumerable Tokens, int Index, string Name, NubType Type, Optional Value) : BoundDefinitionNode(Tokens); public record BoundStructNode(IEnumerable Tokens, string Namespace, string Name, List Fields) : BoundTopLevelNode(Tokens, Namespace); public record TraitFuncNode(IEnumerable Tokens, string Name, List Parameters, NubType ReturnType) : DefinitionNode(Tokens); public record TraitNode(IEnumerable Tokens, string Namespace, string Name, List Functions) : TopLevelNode(Tokens, Namespace); -public record BoundTraitFuncNode(IEnumerable Tokens, string Name, List Parameters, BoundNubType ReturnType) : BoundDefinitionNode(Tokens); +public record BoundTraitFuncNode(IEnumerable Tokens, string Name, List Parameters, NubType ReturnType) : BoundDefinitionNode(Tokens); public record BoundTraitNode(IEnumerable Tokens, string Namespace, string Name, List Functions) : BoundTopLevelNode(Tokens, Namespace); public record TraitFuncImplNode(IEnumerable Tokens, string Name, List Parameters, NubType ReturnType, BlockNode Body) : DefinitionNode(Tokens); public record TraitImplNode(IEnumerable Tokens, string Namespace, NubType TraitType, NubType ForType, List Functions) : TopLevelNode(Tokens, Namespace); -public record BoundTraitFuncImplNode(IEnumerable Tokens, string Name, List Parameters, BoundNubType ReturnType, BoundBlock Body) : BoundDefinitionNode(Tokens); -public record BoundTraitImplNode(IEnumerable Tokens, string Namespace, BoundNubType TraitType, BoundNubType ForType, List Functions) : BoundTopLevelNode(Tokens, Namespace); \ No newline at end of file +public record BoundTraitFuncImplNode(IEnumerable Tokens, string Name, List Parameters, NubType ReturnType, BoundBlock Body) : BoundDefinitionNode(Tokens); +public record BoundTraitImplNode(IEnumerable Tokens, string Namespace, NubType TraitType, NubType ForType, List Functions) : BoundTopLevelNode(Tokens, Namespace); \ No newline at end of file diff --git a/src/compiler/NubLang/Syntax/Node/Expression.cs b/src/compiler/NubLang/Syntax/Node/Expression.cs index 34908ea..60179bf 100644 --- a/src/compiler/NubLang/Syntax/Node/Expression.cs +++ b/src/compiler/NubLang/Syntax/Node/Expression.cs @@ -24,44 +24,44 @@ public enum BinaryExpressionOperator } public abstract record ExpressionNode(IEnumerable Tokens) : Node(Tokens); -public abstract record BoundExpressionNode(IEnumerable Tokens, BoundNubType Type) : BoundNode(Tokens); +public abstract record BoundExpressionNode(IEnumerable Tokens, NubType Type) : BoundNode(Tokens); public record BinaryExpressionNode(IEnumerable Tokens, ExpressionNode Left, BinaryExpressionOperator Operator, ExpressionNode Right) : ExpressionNode(Tokens); -public record BoundBinaryExpressionNode(IEnumerable Tokens, BoundNubType Type, BoundExpressionNode Left, BinaryExpressionOperator Operator, BoundExpressionNode Right) : BoundExpressionNode(Tokens, Type); +public record BoundBinaryExpressionNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Left, BinaryExpressionOperator Operator, BoundExpressionNode Right) : BoundExpressionNode(Tokens, Type); public record UnaryExpressionNode(IEnumerable Tokens, UnaryExpressionOperator Operator, ExpressionNode Operand) : ExpressionNode(Tokens); -public record BoundUnaryExpressionNode(IEnumerable Tokens, BoundNubType Type, UnaryExpressionOperator Operator, BoundExpressionNode Operand) : BoundExpressionNode(Tokens, Type); +public record BoundUnaryExpressionNode(IEnumerable Tokens, NubType Type, UnaryExpressionOperator Operator, BoundExpressionNode Operand) : BoundExpressionNode(Tokens, Type); public record FuncCallNode(IEnumerable Tokens, ExpressionNode Expression, List Parameters) : ExpressionNode(Tokens); -public record BoundFuncCallNode(IEnumerable Tokens, BoundNubType Type, BoundExpressionNode Expression, List Parameters) : BoundExpressionNode(Tokens, Type); +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 BoundVariableIdentNode(IEnumerable Tokens, BoundNubType Type, string Name) : BoundExpressionNode(Tokens, Type); -public record BoundLocalFuncIdentNode(IEnumerable Tokens, BoundNubType Type, string Namespace, string Name) : BoundExpressionNode(Tokens, Type); -public record BoundExternFuncIdentNode(IEnumerable Tokens, BoundNubType Type, string 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, BoundNubType Type, BoundExpressionNode Capacity, BoundNubType ElementType) : BoundExpressionNode(Tokens, Type); +public record BoundArrayInitializerNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Capacity, NubType ElementType) : BoundExpressionNode(Tokens, Type); public record ArrayIndexAccessNode(IEnumerable Tokens, ExpressionNode Target, ExpressionNode Index) : ExpressionNode(Tokens); -public record BoundArrayIndexAccessNode(IEnumerable Tokens, BoundNubType Type, BoundExpressionNode Target, BoundExpressionNode Index) : BoundExpressionNode(Tokens, Type); +public record BoundArrayIndexAccessNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Target, BoundExpressionNode Index) : BoundExpressionNode(Tokens, Type); public record AnonymousFuncNode(IEnumerable Tokens, List Parameters, BlockNode Body, NubType ReturnType) : ExpressionNode(Tokens); -public record BoundAnonymousFuncNode(IEnumerable Tokens, BoundNubType Type, List Parameters, BoundBlock Body, BoundNubType ReturnType) : BoundExpressionNode(Tokens, Type); +public record BoundAnonymousFuncNode(IEnumerable Tokens, NubType Type, List Parameters, BoundBlock Body, NubType ReturnType) : BoundExpressionNode(Tokens, Type); public record AddressOfNode(IEnumerable Tokens, ExpressionNode Expression) : ExpressionNode(Tokens); -public record BoundAddressOfNode(IEnumerable Tokens, BoundNubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type); +public record BoundAddressOfNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type); public record LiteralNode(IEnumerable Tokens, string Literal, LiteralKind Kind) : ExpressionNode(Tokens); -public record BoundLiteralNode(IEnumerable Tokens, BoundNubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type); +public record BoundLiteralNode(IEnumerable Tokens, NubType Type, string Literal, LiteralKind Kind) : BoundExpressionNode(Tokens, Type); public record MemberAccessNode(IEnumerable Tokens, ExpressionNode Target, string Member) : ExpressionNode(Tokens); -public record BoundStructFieldAccessNode(IEnumerable Tokens, BoundNubType Type, BoundNubStructType StructType, BoundExpressionNode Target, string Field) : BoundExpressionNode(Tokens, Type); -public record BoundTraitImplFuncAccessNode(IEnumerable Tokens, BoundNubType Type, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type); -public record BoundTraitFuncAccessNode(IEnumerable Tokens, BoundNubType Type, BoundNubTraitType TraitType, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type); +public record BoundStructFieldAccessNode(IEnumerable Tokens, NubType Type, NubCustomType 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, NubCustomType TraitType, BoundExpressionNode Target, string FuncName) : BoundExpressionNode(Tokens, Type); public record StructInitializerNode(IEnumerable Tokens, NubType StructType, Dictionary Initializers) : ExpressionNode(Tokens); -public record BoundStructInitializerNode(IEnumerable Tokens, BoundNubType Type, BoundNubStructType StructType, Dictionary Initializers) : BoundExpressionNode(Tokens, Type); +public record BoundStructInitializerNode(IEnumerable Tokens, NubType Type, NubCustomType StructType, Dictionary Initializers) : BoundExpressionNode(Tokens, Type); public record DereferenceNode(IEnumerable Tokens, ExpressionNode Expression) : ExpressionNode(Tokens); -public record BoundDereferenceNode(IEnumerable Tokens, BoundNubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type); \ No newline at end of file +public record BoundDereferenceNode(IEnumerable Tokens, NubType Type, BoundExpressionNode Expression) : BoundExpressionNode(Tokens, Type); \ No newline at end of file diff --git a/src/compiler/NubLang/Syntax/Node/Statement.cs b/src/compiler/NubLang/Syntax/Node/Statement.cs index f04d0d2..5825b60 100644 --- a/src/compiler/NubLang/Syntax/Node/Statement.cs +++ b/src/compiler/NubLang/Syntax/Node/Statement.cs @@ -20,7 +20,7 @@ public record IfNode(IEnumerable Tokens, ExpressionNode Condition, BlockN public record BoundIfNode(IEnumerable Tokens, BoundExpressionNode Condition, BoundBlock Body, Optional> Else) : BoundStatementNode(Tokens); public record VariableDeclarationNode(IEnumerable Tokens, string Name, Optional ExplicitType, Optional Assignment) : StatementNode(Tokens); -public record BoundVariableDeclarationNode(IEnumerable Tokens, string Name, Optional Assignment, BoundNubType Type) : BoundStatementNode(Tokens); +public record BoundVariableDeclarationNode(IEnumerable Tokens, string Name, Optional Assignment, NubType Type) : BoundStatementNode(Tokens); public record ContinueNode(IEnumerable Tokens) : StatementNode(Tokens); public record BoundContinueNode(IEnumerable Tokens) : BoundStatementNode(Tokens);