From 1cf7f1884ab1d67146197c7e7e25e1033aff9718 Mon Sep 17 00:00:00 2001 From: nub31 Date: Fri, 12 Sep 2025 22:08:26 +0200 Subject: [PATCH] Remove interfaces --- compiler/NubLang.CLI/Program.cs | 8 +- compiler/NubLang/Diagnostics/Diagnostic.cs | 1 - .../NubLang/Generation/QBE/QBEGenerator.cs | 127 ++---------------- compiler/NubLang/Modules/Module.cs | 17 --- compiler/NubLang/Modules/ModuleRepository.cs | 12 -- compiler/NubLang/Parsing/Parser.cs | 46 +------ .../Parsing/Syntax/DefinitionSyntax.cs | 6 +- compiler/NubLang/Tokenization/Token.cs | 1 - compiler/NubLang/Tokenization/Tokenizer.cs | 1 - .../TypeChecking/Node/DefinitionNode.cs | 6 +- .../TypeChecking/Node/ExpressionNode.cs | 7 +- .../NubLang/TypeChecking/Node/TypeNode.cs | 20 +-- compiler/NubLang/TypeChecking/TypeChecker.cs | 76 +---------- example/makefile | 4 +- 14 files changed, 32 insertions(+), 300 deletions(-) diff --git a/compiler/NubLang.CLI/Program.cs b/compiler/NubLang.CLI/Program.cs index 9daddd1..1bed091 100644 --- a/compiler/NubLang.CLI/Program.cs +++ b/compiler/NubLang.CLI/Program.cs @@ -66,7 +66,6 @@ var moduleRepository = new ModuleRepository(syntaxTrees); var definitions = new List(); var referencedStructTypes = new HashSet(); -var referencedInterfaceTypes = new HashSet(); foreach (var syntaxTree in syntaxTrees) { @@ -80,11 +79,6 @@ foreach (var syntaxTree in syntaxTrees) { referencedStructTypes.Add(structType); } - - foreach (var interfaceType in typeChecker.ReferencedInterfaceTypes) - { - referencedInterfaceTypes.Add(interfaceType); - } } foreach (var diagnostic in diagnostics) @@ -99,7 +93,7 @@ if (diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Erro Directory.CreateDirectory(".build"); -var generator = new QBEGenerator(definitions, referencedStructTypes, referencedInterfaceTypes); +var generator = new QBEGenerator(definitions, referencedStructTypes); var ssa = generator.Emit(); var ssaFilePath = Path.Combine(".build", "out.ssa"); File.WriteAllText(ssaFilePath, ssa); diff --git a/compiler/NubLang/Diagnostics/Diagnostic.cs b/compiler/NubLang/Diagnostics/Diagnostic.cs index dd9da68..bd640db 100644 --- a/compiler/NubLang/Diagnostics/Diagnostic.cs +++ b/compiler/NubLang/Diagnostics/Diagnostic.cs @@ -271,7 +271,6 @@ public class Diagnostic case Symbol.Struct: case Symbol.Let: case Symbol.Calls: - case Symbol.Interface: case Symbol.For: case Symbol.Extern: { diff --git a/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/compiler/NubLang/Generation/QBE/QBEGenerator.cs index 4e7aca7..908a9c8 100644 --- a/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -11,7 +11,6 @@ public class QBEGenerator private readonly QBEWriter _writer; private readonly List _definitions; private readonly HashSet _structTypes; - private readonly HashSet _interfaceTypes; private readonly List _cStringLiterals = []; private readonly List _stringLiterals = []; @@ -23,11 +22,10 @@ public class QBEGenerator private int _stringLiteralIndex; private bool _codeIsReachable = true; - public QBEGenerator(List definitions, HashSet structTypes, HashSet interfaceTypes) + public QBEGenerator(List definitions, HashSet structTypes) { _definitions = definitions; _structTypes = structTypes; - _interfaceTypes = interfaceTypes; _writer = new QBEWriter(); } @@ -261,8 +259,8 @@ public class QBEGenerator return; } - // Structs and interfaces has known sizes at compile time - if (complexType is StructTypeNode or InterfaceTypeNode) + // Structs has known sizes at compile time + if (complexType is StructTypeNode) { var value = EmitExpression(source); _writer.Indented($"blit {value}, {destination}, {SizeOf(complexType)}"); @@ -289,7 +287,7 @@ public class QBEGenerator private string EmitCopy(ExpressionNode source) { // Allowlist for types which are safe to not copy - if (source is ArrayInitializerNode or StructInitializerNode or ConvertToInterfaceNode or LiteralNode) + if (source is ArrayInitializerNode or StructInitializerNode or LiteralNode) { return EmitExpression(source); } @@ -304,8 +302,8 @@ public class QBEGenerator var value = EmitExpression(source); var destination = TmpName(); - // Structs and interfaces has known sizes at compile time - if (complexType is StructTypeNode or InterfaceTypeNode) + // Structs has known sizes at compile time + if (complexType is StructTypeNode) { var size = SizeOf(complexType); _writer.Indented($"{destination} =l alloc8 {size}"); @@ -501,12 +499,6 @@ public class QBEGenerator private void EmitStatement(StatementNode statement) { - // var tokens = statement.Tokens.ToArray(); - // if (tokens.Length != 0) - // { - // _writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}"); - // } - switch (statement) { case AssignmentNode assignment: @@ -622,12 +614,6 @@ public class QBEGenerator private string EmitExpression(ExpressionNode expression) { - // var tokens = expression.Tokens.ToArray(); - // if (tokens.Length != 0) - // { - // _writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}"); - // } - return expression switch { ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer), @@ -636,8 +622,6 @@ public class QBEGenerator DereferenceNode dereference => EmitDereference(dereference), BinaryExpressionNode binary => EmitBinaryExpression(binary), FuncCallNode funcCall => EmitFuncCall(funcCall), - InterfaceFuncCallNode interfaceFuncCall => EmitInterfaceFuncCall(interfaceFuncCall), - ConvertToInterfaceNode convertToInterface => EmitConvertToInterface(convertToInterface), ConvertIntNode convertInt => EmitConvertInt(convertInt), ConvertFloatNode convertFloat => EmitConvertFloat(convertFloat), VariableIdentifierNode identifier => EmitVariableIdentifier(identifier), @@ -673,14 +657,13 @@ public class QBEGenerator private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess) { - // var address = EmitAddressOfArrayIndexAccess(arrayIndexAccess); - // if (arrayIndexAccess.Type is StructTypeNode) - // { - // return address; - // } - // - // return EmitLoad(arrayIndexAccess.Type, address); - throw new NotImplementedException(); + var address = EmitAddressOfArrayIndexAccess(arrayIndexAccess); + if (arrayIndexAccess.Type is StructTypeNode) + { + return address; + } + + return EmitLoad(arrayIndexAccess.Type, address); } private string EmitArrayInitializer(ArrayInitializerNode arrayInitializer) @@ -1114,76 +1097,6 @@ public class QBEGenerator } } - private string EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall) - { - var target = EmitExpression(interfaceFuncCall.InterfaceExpression); - - var functionIndex = interfaceFuncCall.InterfaceType.Functions.ToList().FindIndex(x => x.Name == interfaceFuncCall.Name); - var offset = functionIndex * 8; - - var vtable = TmpName(); - _writer.Indented($"{vtable} =l loadl {target}"); - - var funcOffset = TmpName(); - _writer.Indented($"{funcOffset} =l add {vtable}, {offset}"); - - var func = TmpName(); - _writer.Indented($"{func} =l loadl {funcOffset}"); - - var data = TmpName(); - _writer.Indented($"{data} =l add {target}, 8"); - _writer.Indented($"{data} =l loadl {data}"); - - List parameterStrings = [$"l {data}"]; - - foreach (var parameter in interfaceFuncCall.Parameters) - { - var copy = EmitCopy(parameter); - parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}"); - } - - if (interfaceFuncCall.Type is VoidTypeNode) - { - _writer.Indented($"call {func}({string.Join(", ", parameterStrings)})"); - return string.Empty; - } - else - { - var outputName = TmpName(); - _writer.Indented($"{outputName} {QBEAssign(interfaceFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})"); - return outputName; - } - } - - private string EmitConvertToInterface(ConvertToInterfaceNode convertToInterface) - { - var implementation = EmitExpression(convertToInterface.Implementation); - - var vtableOffset = 0; - foreach (var interfaceImplementation in convertToInterface.StructType.InterfaceImplementations) - { - if (interfaceImplementation == convertToInterface.InterfaceType) - { - break; - } - - vtableOffset += interfaceImplementation.Functions.Count * 8; - } - - var destination = TmpName(); - _writer.Indented($"{destination} =l alloc8 {SizeOf(convertToInterface.InterfaceType)}"); - - var interfaceVtablePointer = TmpName(); - _writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(convertToInterface.StructType.Module, convertToInterface.StructType.Name)}, {vtableOffset}"); - _writer.Indented($"storel {interfaceVtablePointer}, {destination}"); - - var objectPointer = TmpName(); - _writer.Indented($"{objectPointer} =l add {destination}, 8"); - _writer.Indented($"storel {implementation}, {objectPointer}"); - - return destination; - } - private string EmitConvertInt(ConvertIntNode convertInt) { var value = EmitExpression(convertInt.Value); @@ -1279,7 +1192,6 @@ public class QBEGenerator StringTypeNode => 8, ArrayTypeNode => 8, StructTypeNode structType => CalculateStructSize(structType), - InterfaceTypeNode => 16, _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type.GetType()}") }; } @@ -1288,8 +1200,6 @@ public class QBEGenerator { var offset = 0; - var fields = new List(structType.Fields.Count); - foreach (var field in structType.Fields) { var fieldAlignment = AlignmentOf(field.Type); @@ -1318,7 +1228,6 @@ public class QBEGenerator StringTypeNode => 8, ArrayTypeNode => 8, StructTypeNode structType => CalculateStructAlignment(structType), - InterfaceTypeNode => 8, _ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type.GetType()}") }; } @@ -1327,11 +1236,6 @@ public class QBEGenerator { var maxAlignment = 1; - if (structType.InterfaceImplementations.Any()) - { - maxAlignment = Math.Max(maxAlignment, 8); - } - foreach (var field in structType.Fields) { var fieldAlignment = AlignmentOf(field.Type); @@ -1405,11 +1309,6 @@ public class QBEGenerator { return $"$.{module}.{structName}.func.{funcName}"; } - - private static string StructVtableName(string module, string structName) - { - return $"${module}.{structName}.vtable"; - } } public class StringLiteral(string value, string name) diff --git a/compiler/NubLang/Modules/Module.cs b/compiler/NubLang/Modules/Module.cs index 26ff5f1..bee7c02 100644 --- a/compiler/NubLang/Modules/Module.cs +++ b/compiler/NubLang/Modules/Module.cs @@ -5,7 +5,6 @@ namespace NubLang.Modules; public class Module { private readonly List _structs = []; - private readonly List _interfaces = []; private readonly List _functions = []; public void RegisterStruct(bool exported, string name, List fields, List functions) @@ -13,11 +12,6 @@ public class Module _structs.Add(new ModuleStruct(exported, name, fields, functions)); } - public void RegisterInterface(bool exported, string name, List functions) - { - _interfaces.Add(new ModuleInterface(exported, name, functions)); - } - public void RegisterFunction(bool exported, string name, string? externSymbol, List parameters, TypeSyntax returnType) { _functions.Add(new ModuleFunction(exported, name, externSymbol, parameters, returnType)); @@ -28,11 +22,6 @@ public class Module return _structs.Where(x => x.Exported || includePrivate).ToList(); } - public List InterfaceTypes(bool includePrivate) - { - return _interfaces.Where(x => x.Exported || includePrivate).ToList(); - } - public List Functions(bool includePrivate) { return _functions.Where(x => x.Exported || includePrivate).ToList(); @@ -47,12 +36,6 @@ public record ModuleStructFunction(string Name, List Fields, List Functions); -public record ModuleInterfaceFunctionParameter(string Name, TypeSyntax Type); - -public record ModuleInterfaceFunction(string Name, List Parameters, TypeSyntax ReturnType); - -public record ModuleInterface(bool Exported, string Name, List Functions); - public record ModuleFunctionParameter(string Name, TypeSyntax Type); public record ModuleFunction(bool Exported, string Name, string? ExternSymbol, List Parameters, TypeSyntax ReturnType); \ No newline at end of file diff --git a/compiler/NubLang/Modules/ModuleRepository.cs b/compiler/NubLang/Modules/ModuleRepository.cs index 67ba1f0..4a17926 100644 --- a/compiler/NubLang/Modules/ModuleRepository.cs +++ b/compiler/NubLang/Modules/ModuleRepository.cs @@ -42,18 +42,6 @@ public class ModuleRepository module.RegisterStruct(structDef.Exported, structDef.Name, fields, functions); break; } - case InterfaceSyntax interfaceDef: - { - var functions = new List(); - foreach (var function in interfaceDef.Functions) - { - var parameters = function.Signature.Parameters.Select(x => new ModuleInterfaceFunctionParameter(x.Name, x.Type)).ToList(); - functions.AddRange(new ModuleInterfaceFunction(function.Name, parameters, function.Signature.ReturnType)); - } - - module.RegisterInterface(interfaceDef.Exported, interfaceDef.Name, functions); - break; - } default: { throw new ArgumentOutOfRangeException(nameof(definition)); diff --git a/compiler/NubLang/Parsing/Parser.cs b/compiler/NubLang/Parsing/Parser.cs index 0875f4d..be20d21 100644 --- a/compiler/NubLang/Parsing/Parser.cs +++ b/compiler/NubLang/Parsing/Parser.cs @@ -84,14 +84,13 @@ public sealed class Parser } var keyword = ExpectSymbol(); - var definition = keyword.Symbol switch + DefinitionSyntax definition = keyword.Symbol switch { Symbol.Func => ParseFunc(startIndex, exported, null), Symbol.Struct => ParseStruct(startIndex, exported), - Symbol.Interface => ParseInterface(startIndex, exported), _ => throw new ParseException(Diagnostic - .Error($"Expected 'func', 'struct' or 'interface' but found '{keyword.Symbol}'") - .WithHelp("Valid definition keywords are 'func', 'struct' and 'interface'") + .Error($"Expected 'func' or 'struct' but found '{keyword.Symbol}'") + .WithHelp("Valid definition keywords are 'func' and 'struct'") .At(keyword) .Build()) }; @@ -103,7 +102,7 @@ public sealed class Parser _diagnostics.Add(e.Diagnostic); while (HasToken) { - if (CurrentToken is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Interface }) + if (CurrentToken is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct }) { break; } @@ -164,19 +163,9 @@ public sealed class Parser return new FuncSyntax(GetTokens(startIndex), name.Value, exported, externSymbol, signature, body); } - private DefinitionSyntax ParseStruct(int startIndex, bool exported) + private StructSyntax ParseStruct(int startIndex, bool exported) { var name = ExpectIdentifier(); - var interfaceImplementations = new List(); - - if (TryExpectSymbol(Symbol.Colon)) - { - do - { - var interfaceType = ParseType(); - interfaceImplementations.Add(interfaceType); - } while (TryExpectSymbol(Symbol.Comma)); - } ExpectSymbol(Symbol.OpenBrace); @@ -212,30 +201,7 @@ public sealed class Parser } } - return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields, funcs, interfaceImplementations); - } - - private InterfaceSyntax ParseInterface(int startIndex, bool exported) - { - var name = ExpectIdentifier(); - - ExpectSymbol(Symbol.OpenBrace); - - List functions = []; - - while (!TryExpectSymbol(Symbol.CloseBrace)) - { - var funcStartIndex = _tokenIndex; - - ExpectSymbol(Symbol.Func); - - var funcName = ExpectIdentifier().Value; - var signature = ParseFuncSignature(); - - functions.Add(new InterfaceFuncSyntax(GetTokens(funcStartIndex), funcName, signature)); - } - - return new InterfaceSyntax(GetTokens(startIndex), name.Value, exported, functions); + return new StructSyntax(GetTokens(startIndex), name.Value, exported, fields, funcs); } private StatementSyntax ParseStatement() diff --git a/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs b/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs index 26bab02..0a929f3 100644 --- a/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs +++ b/compiler/NubLang/Parsing/Syntax/DefinitionSyntax.cs @@ -14,8 +14,4 @@ public record StructFieldSyntax(IEnumerable Tokens, string Name, TypeSynt public record StructFuncSyntax(IEnumerable Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : SyntaxNode(Tokens); -public record StructSyntax(IEnumerable Tokens, string Name, bool Exported, List Fields, List Functions, List InterfaceImplementations) : DefinitionSyntax(Tokens, Name, Exported); - -public record InterfaceFuncSyntax(IEnumerable Tokens, string Name, FuncSignatureSyntax Signature) : SyntaxNode(Tokens); - -public record InterfaceSyntax(IEnumerable Tokens, string Name, bool Exported, List Functions) : DefinitionSyntax(Tokens, Name, Exported); \ No newline at end of file +public record StructSyntax(IEnumerable Tokens, string Name, bool Exported, List Fields, List Functions) : DefinitionSyntax(Tokens, Name, Exported); \ No newline at end of file diff --git a/compiler/NubLang/Tokenization/Token.cs b/compiler/NubLang/Tokenization/Token.cs index 50eb69d..ec9709b 100644 --- a/compiler/NubLang/Tokenization/Token.cs +++ b/compiler/NubLang/Tokenization/Token.cs @@ -67,7 +67,6 @@ public enum Symbol Ampersand, Let, Calls, - Interface, For, Extern, Semi, diff --git a/compiler/NubLang/Tokenization/Tokenizer.cs b/compiler/NubLang/Tokenization/Tokenizer.cs index e945986..33ff5f1 100644 --- a/compiler/NubLang/Tokenization/Tokenizer.cs +++ b/compiler/NubLang/Tokenization/Tokenizer.cs @@ -17,7 +17,6 @@ public sealed class Tokenizer ["struct"] = Symbol.Struct, ["let"] = Symbol.Let, ["calls"] = Symbol.Calls, - ["interface"] = Symbol.Interface, ["for"] = Symbol.For, ["extern"] = Symbol.Extern, ["module"] = Symbol.Module, diff --git a/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs b/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs index 46c8afb..cfecb44 100644 --- a/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs +++ b/compiler/NubLang/TypeChecking/Node/DefinitionNode.cs @@ -12,8 +12,4 @@ public record StructFieldNode(string Name, TypeNode Type, Optional Fields, List Functions, List InterfaceImplementations) : DefinitionNode(Module, Name); - -public record InterfaceFuncNode(string Name, FuncSignatureNode Signature) : Node; - -public record InterfaceNode(InterfaceTypeNode InterfaceType, string Module, string Name, List Functions) : DefinitionNode(Module, Name); \ No newline at end of file +public record StructNode(StructTypeNode StructType, string Module, string Name, List Fields, List Functions) : DefinitionNode(Module, Name); \ No newline at end of file diff --git a/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs b/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs index 80b6974..0f68754 100644 --- a/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs +++ b/compiler/NubLang/TypeChecking/Node/ExpressionNode.cs @@ -33,6 +33,7 @@ public enum BinaryOperator public abstract record ExpressionNode(TypeNode Type) : Node; public abstract record LValueExpressionNode(TypeNode Type) : RValueExpressionNode(Type); + public abstract record RValueExpressionNode(TypeNode Type) : ExpressionNode(Type); public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : RValueExpressionNode(Type); @@ -43,8 +44,6 @@ public record FuncCallNode(TypeNode Type, ExpressionNode Expression, List Parameters) : RValueExpressionNode(Type); -public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, List Parameters) : RValueExpressionNode(Type); - public record VariableIdentifierNode(TypeNode Type, string Name) : LValueExpressionNode(Type); public record FuncParameterIdentifierNode(TypeNode Type, string Name) : RValueExpressionNode(Type); @@ -65,8 +64,6 @@ public record StructInitializerNode(StructTypeNode StructType, Dictionary fields, List functions, List interfaceImplementations) : ComplexTypeNode +public class StructTypeNode(string module, string name, List fields, List functions) : ComplexTypeNode { public string Module { get; } = module; public string Name { get; } = name; public List Fields { get; set; } = fields; public List Functions { get; set; } = functions; - public List InterfaceImplementations { get; set; } = interfaceImplementations; public override string ToString() => Name; public override bool Equals(TypeNode? other) => other is StructTypeNode structType && Name == structType.Name && Module == structType.Module; public override int GetHashCode() => HashCode.Combine(typeof(StructTypeNode), Name); } -public class InterfaceTypeFunc(string name, FuncTypeNode type) -{ - public string Name { get; } = name; - public FuncTypeNode Type { get; } = type; -} - -public class InterfaceTypeNode(string module, string name, List functions) : ComplexTypeNode -{ - public string Module { get; } = module; - public string Name { get; } = name; - public List Functions { get; set; } = functions; - - public override string ToString() => Name; - public override bool Equals(TypeNode? other) => other is InterfaceTypeNode interfaceType && Name == interfaceType.Name && Module == interfaceType.Module; - public override int GetHashCode() => HashCode.Combine(typeof(InterfaceTypeNode), Name); -} - public class ArrayTypeNode(TypeNode elementType) : ComplexTypeNode { public TypeNode ElementType { get; } = elementType; diff --git a/compiler/NubLang/TypeChecking/TypeChecker.cs b/compiler/NubLang/TypeChecking/TypeChecker.cs index 428c54c..2fa08dd 100644 --- a/compiler/NubLang/TypeChecking/TypeChecker.cs +++ b/compiler/NubLang/TypeChecking/TypeChecker.cs @@ -16,7 +16,6 @@ public sealed class TypeChecker private readonly Stack _funcReturnTypes = []; private readonly List _diagnostics = []; private readonly List _referencedStructTypes = []; - private readonly List _referencedInterfaceTypes = []; private readonly List _definitions = []; private Scope Scope => _scopes.Peek(); @@ -33,7 +32,6 @@ public sealed class TypeChecker public List Definitions => _definitions; public List Diagnostics => _diagnostics; public List ReferencedStructTypes => _referencedStructTypes; - public List ReferencedInterfaceTypes => _referencedInterfaceTypes; public void Check() { @@ -41,7 +39,6 @@ public sealed class TypeChecker _funcReturnTypes.Clear(); _diagnostics.Clear(); _referencedStructTypes.Clear(); - _referencedInterfaceTypes.Clear(); _definitions.Clear(); foreach (var definition in _syntaxTree.Definitions) @@ -61,32 +58,12 @@ public sealed class TypeChecker { return node switch { - InterfaceSyntax definition => CheckInterfaceDefinition(definition), FuncSyntax definition => CheckFuncDefinition(definition), StructSyntax definition => CheckStructDefinition(definition), _ => throw new ArgumentOutOfRangeException(nameof(node)) }; } - private InterfaceNode CheckInterfaceDefinition(InterfaceSyntax node) - { - var functions = node.Functions - .Select(function => new InterfaceFuncNode(function.Name, CheckFuncSignature(function.Signature))) - .ToList(); - - var functionTypes = new List(); - foreach (var function in node.Functions) - { - var parameters = function.Signature.Parameters.Select(x => ResolveType(x.Type)).ToList(); - var funcType = new FuncTypeNode(parameters, ResolveType(function.Signature.ReturnType)); - functionTypes.Add(new InterfaceTypeFunc(function.Name, funcType)); - } - - var type = new InterfaceTypeNode(_syntaxTree.Metadata.ModuleName, node.Name, functionTypes); - - return new InterfaceNode(type, _syntaxTree.Metadata.ModuleName, node.Name, functions); - } - private StructNode CheckStructDefinition(StructSyntax node) { var fields = new List(); @@ -117,19 +94,6 @@ public sealed class TypeChecker functions.Add(new StructFuncNode(function.Name, CheckFuncSignature(function.Signature), body)); } - var interfaceImplementations = new List(); - foreach (var interfaceImplementation in node.InterfaceImplementations) - { - var resolvedType = ResolveType(interfaceImplementation); - if (resolvedType is not InterfaceTypeNode interfaceType) - { - _diagnostics.Add(Diagnostic.Error($"Struct {node.Name} cannot implement non-struct type {interfaceImplementation}").At(interfaceImplementation).Build()); - continue; - } - - interfaceImplementations.Add(interfaceType); - } - var fieldTypes = node.Fields .Select(x => new StructTypeField(x.Name, ResolveType(x.Type), x.Value.HasValue)) .ToList(); @@ -142,22 +106,9 @@ public sealed class TypeChecker functionTypes.Add(new StructTypeFunc(function.Name, funcType)); } - var interfaceImplementationTypes = new List(); - foreach (var interfaceImplementation in node.InterfaceImplementations) - { - var resolvedType = ResolveType(interfaceImplementation); - if (resolvedType is not InterfaceTypeNode interfaceType) - { - _diagnostics.Add(Diagnostic.Error($"Struct {node.Name} cannot implement non-struct type {interfaceImplementation}").At(interfaceImplementation).Build()); - continue; - } + var type = new StructTypeNode(_syntaxTree.Metadata.ModuleName, node.Name, fieldTypes, functionTypes); - interfaceImplementationTypes.Add(interfaceType); - } - - var type = new StructTypeNode(_syntaxTree.Metadata.ModuleName, node.Name, fieldTypes, functionTypes, interfaceImplementationTypes); - - return new StructNode(type, _syntaxTree.Metadata.ModuleName, node.Name, fields, functions, interfaceImplementations); + return new StructNode(type, _syntaxTree.Metadata.ModuleName, node.Name, fields, functions); } private FuncNode CheckFuncDefinition(FuncSyntax node) @@ -289,11 +240,6 @@ public sealed class TypeChecker return result; } - if (result.Type is StructTypeNode structType && expectedType is InterfaceTypeNode interfaceType) - { - return new ConvertToInterfaceNode(interfaceType, interfaceType, structType, result); - } - if (result.Type is IntTypeNode sourceIntType && expectedType is IntTypeNode targetIntType) { if (sourceIntType.Signed == targetIntType.Signed && sourceIntType.Width < targetIntType.Width) @@ -586,7 +532,7 @@ public sealed class TypeChecker if (!_resolvingTypes.Add(key)) { - var placeholder = new StructTypeNode(customType.Module, customType.Name, new List(), [], []); + var placeholder = new StructTypeNode(customType.Module, customType.Name, [], []); _typeCache[key] = placeholder; return placeholder; } @@ -603,30 +549,18 @@ public sealed class TypeChecker var structType = module.StructTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); if (structType != null) { - var result = new StructTypeNode(customType.Module, structType.Name, [], [], []); + var result = new StructTypeNode(customType.Module, structType.Name, [], []); _typeCache[key] = result; var fields = structType.Fields.Select(x => new StructTypeField(x.Name, ResolveType(x.Type), x.HasDefaultValue)).ToList(); result.Fields.AddRange(fields); - // todo(nub31): Functions and interface implementations + // todo(nub31): Function implementations _referencedStructTypes.Add(result); return result; } - var interfaceType = module.InterfaceTypes(includePrivate).FirstOrDefault(x => x.Name == customType.Name); - if (interfaceType != null) - { - var result = new InterfaceTypeNode(customType.Module, interfaceType.Name, []); - _typeCache[key] = result; - - // todo(nub31): Put func resolution code here - - _referencedInterfaceTypes.AddRange(result); - return result; - } - throw new TypeCheckerException(Diagnostic.Error($"Type {customType.Name} not found in module {customType.Module}").At(customType).Build()); } finally diff --git a/example/makefile b/example/makefile index 32cd5ab..302a9aa 100644 --- a/example/makefile +++ b/example/makefile @@ -3,8 +3,8 @@ NUBC = ../compiler/NubLang.CLI/bin/Debug/net9.0/nubc out: .build/out.o gcc -nostartfiles -o out x86_64.s .build/out.o -.build/out.o: $(NUBC) src/main.nub src/test.nub - $(NUBC) src/main.nub src/test.nub +.build/out.o: $(NUBC) src/main.nub + $(NUBC) src/main.nub .PHONY: $(NUBC) $(NUBC):