diff --git a/src/compiler/Syntax/DefinitionTable.cs b/src/compiler/Syntax/DefinitionTable.cs index 313ecfe..1f8cd25 100644 --- a/src/compiler/Syntax/DefinitionTable.cs +++ b/src/compiler/Syntax/DefinitionTable.cs @@ -53,7 +53,7 @@ public class DefinitionTable var implementations = _syntaxTrees .SelectMany(c => c.Definitions) .OfType() - .Where(c => c.ForType.Equals(type)); + .Where(c => c.ForType == type); var implementation = implementations.SingleOrDefault(c => c.Functions.Any(x => x.Name == funcName)); @@ -164,7 +164,7 @@ public class BoundDefinitionTable var implementations = _syntaxTrees .SelectMany(c => c.Definitions) .OfType() - .Where(c => c.ForType.Equals(type)); + .Where(c => c.ForType == type); var implementation = implementations.SingleOrDefault(c => c.Functions.Any(x => x.Name == funcName)); diff --git a/src/compiler/Syntax/Typing/TypeChecker.cs b/src/compiler/Syntax/Typing/TypeChecker.cs deleted file mode 100644 index e935a2b..0000000 --- a/src/compiler/Syntax/Typing/TypeChecker.cs +++ /dev/null @@ -1,633 +0,0 @@ -// using System.Diagnostics; -// using Syntax.Diagnostics; -// using Syntax.Parsing; -// using Syntax.Parsing.Node; -// using Syntax.Tokenization; -// -// namespace Syntax.Typing; -// -// public static class TypeChecker -// { -// private static SyntaxTree _syntaxTree = null!; -// private static DefinitionTable _definitionTable = null!; -// -// private static Dictionary _variables = new(); -// private static List _diagnostics = []; -// private static NubType? _currentFunctionReturnType; -// private static Queue _anonymousFunctions = []; -// -// public static void Check(SyntaxTree syntaxTree, DefinitionTable definitionTable, out IEnumerable diagnostics) -// { -// _syntaxTree = syntaxTree; -// _definitionTable = definitionTable; -// -// _variables = new Dictionary(); -// _diagnostics = []; -// _currentFunctionReturnType = null; -// _anonymousFunctions = []; -// -// foreach (var structDef in syntaxTree.Definitions.OfType()) -// { -// CheckStructDef(structDef); -// } -// -// foreach (var funcDef in syntaxTree.Definitions.OfType()) -// { -// CheckFuncDef(funcDef.Parameters, funcDef.Body, funcDef.ReturnType); -// } -// -// while (_anonymousFunctions.TryDequeue(out var func)) -// { -// CheckFuncDef(func.Parameters, func.Body, func.ReturnType); -// -// } -// -// diagnostics = _diagnostics; -// } -// -// private static void CheckStructDef(StructDefinitionNode structDef) -// { -// var fields = new Dictionary(); -// foreach (var field in structDef.Fields) -// { -// if (fields.ContainsKey(field.Name)) -// { -// ReportError($"Duplicate field '{field.Name}' in struct '{structDef.Name}'", structDef); -// continue; -// } -// -// if (field.Value.HasValue) -// { -// var fieldType = CheckExpression(field.Value.Value, field.Type); -// if (fieldType != null && !fieldType.Equals(field.Type)) -// { -// ReportError("Default field initializer does not match the defined type", field.Value.Value); -// } -// } -// -// fields[field.Name] = field.Type; -// } -// } -// -// private static void CheckFuncDef(List parameters, BlockNode body, NubType returnType) -// { -// _variables.Clear(); -// _currentFunctionReturnType = returnType; -// -// foreach (var param in parameters) -// { -// _variables[param.Name] = param.Type; -// } -// -// CheckBlock(body); -// } -// -// private static void CheckBlock(BlockNode block) -// { -// foreach (var statement in block.Statements) -// { -// CheckStatement(statement); -// } -// } -// -// private static void CheckStatement(StatementNode statement) -// { -// switch (statement) -// { -// case ArrayIndexAssignmentNode arrayIndexAssignment: -// CheckArrayIndexAssignment(arrayIndexAssignment); -// break; -// case VariableAssignmentNode variableAssignment: -// CheckVariableAssignment(variableAssignment); -// break; -// case VariableDeclarationNode variableDeclaration: -// CheckVariableVariableDeclaration(variableDeclaration); -// break; -// case IfNode ifNode: -// CheckIf(ifNode); -// break; -// case MemberAssignmentNode memberAssignment: -// CheckMemberAssignment(memberAssignment); -// break; -// case WhileNode whileNode: -// CheckWhile(whileNode); -// break; -// case ReturnNode returnNode: -// CheckReturn(returnNode); -// break; -// case StatementExpressionNode statementExpression: -// CheckExpression(statementExpression.Expression); -// break; -// case BreakNode: -// case ContinueNode: -// break; -// case DereferenceAssignmentNode dereferenceAssignment: -// CheckDereferenceAssignment(dereferenceAssignment); -// break; -// default: -// ReportError($"Unsupported statement type: {statement.GetType().Name}", statement); -// break; -// } -// } -// -// private static void CheckMemberAssignment(MemberAssignmentNode memberAssignment) -// { -// var memberType = CheckExpression(memberAssignment.MemberAccess); -// if (memberType == null) return; -// var valueType = CheckExpression(memberAssignment.Value, memberType); -// if (valueType == null) return; -// -// if (!NubType.IsCompatibleWith(memberType, valueType)) -// { -// ReportError($"'{valueType}' is not assignable to member of type '{memberType}'", memberAssignment); -// } -// } -// -// private static void CheckArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment) -// { -// var itemType = CheckExpression(arrayIndexAssignment.ArrayIndexAccess); -// if (itemType == null) return; -// var valueType = CheckExpression(arrayIndexAssignment.Value, itemType); -// if (valueType == null) return; -// -// if (!NubType.IsCompatibleWith(itemType, valueType)) -// { -// ReportError($"'{valueType}' is not assignable to array of type '{itemType}'", arrayIndexAssignment); -// } -// } -// -// private static void CheckVariableAssignment(VariableAssignmentNode variableAssignment) -// { -// if (!_variables.TryGetValue(variableAssignment.Identifier.Name, out var variable)) -// { -// ReportError($"Variable '{variableAssignment.Identifier}' is not declared", variableAssignment); -// return; -// } -// -// var valueType = CheckExpression(variableAssignment.Value, variable); -// if (valueType == null) return; -// -// if (!NubType.IsCompatibleWith(variableAssignment.Value.Type, variable)) -// { -// ReportError($"Cannot assign expression of type '{variableAssignment.Value.Type}' to variable '{variableAssignment.Identifier}' with type '{variable}'", variableAssignment); -// } -// } -// -// private static void CheckVariableVariableDeclaration(VariableDeclarationNode variableDeclaration) -// { -// if (_variables.TryGetValue(variableDeclaration.Name, out var variable)) -// { -// ReportError($"Cannot redeclare variable '{variable}'", variableDeclaration); -// } -// -// _variables[variableDeclaration.Name] = variableDeclaration.Type; -// } -// -// private static NubType? CheckDereference(DereferenceNode dereference) -// { -// var exprType = CheckExpression(dereference.Expression); -// if (exprType == null) return null; -// -// if (exprType is not NubPointerType nubPointerType) -// { -// ReportError($"Cannot dereference a non-pointer type {exprType}", dereference); -// return null; -// } -// -// return nubPointerType.BaseType; -// } -// -// private static NubType CheckFixedInitializerArray(FixedArrayInitializerNode fixedArrayInitializer) -// { -// return new NubFixedArrayType(fixedArrayInitializer.ElementType, fixedArrayInitializer.Capacity); -// } -// -// private static NubType? CheckFuncCall(FuncCallNode funcCall) -// { -// var identType = CheckExpression(funcCall.Expression); -// if (identType is not NubFuncType funcType) -// { -// ReportError("Cannot call function on non-function type", funcCall); -// return null; -// } -// -// if (funcCall.Parameters.Count != funcType.Parameters.Count) -// { -// ReportError($"{funcType} expects {funcType.Parameters.Count} arguments, but was called with {funcType.Parameters.Count} arguments", funcCall); -// return null; -// } -// -// for (var i = 0; i < funcCall.Parameters.Count; i++) -// { -// var parameter = funcCall.Parameters[i]; -// var parameterType = CheckExpression(parameter); -// if (parameterType == null) return null; -// -// if (!NubType.IsCompatibleWith(parameterType, funcType.Parameters[i])) -// { -// ReportError($"'{parameterType}' does not match expected type {funcType.Parameters[i]}", funcCall); -// return null; -// } -// } -// -// return funcType.ReturnType; -// } -// -// private static void CheckIf(IfNode ifNode) -// { -// var conditionType = CheckExpression(ifNode.Condition, NubPrimitiveType.Bool); -// if (conditionType != null && !conditionType.Equals(NubPrimitiveType.Bool)) -// { -// ReportError($"If condition must be a boolean expression, got '{conditionType}'", ifNode.Condition); -// } -// -// CheckBlock(ifNode.Body); -// -// if (ifNode.Else.HasValue) -// { -// var elseValue = ifNode.Else.Value; -// elseValue.Match(CheckIf, CheckBlock); -// } -// } -// -// private static void CheckWhile(WhileNode whileNode) -// { -// var conditionType = CheckExpression(whileNode.Condition, NubPrimitiveType.Bool); -// if (conditionType != null && !conditionType.Equals(NubPrimitiveType.Bool)) -// { -// ReportError($"While condition must be a boolean expression, got '{conditionType}'", whileNode.Condition); -// } -// -// CheckBlock(whileNode.Body); -// } -// -// private static void CheckReturn(ReturnNode returnNode) -// { -// if (returnNode.Value.HasValue) -// { -// var returnType = CheckExpression(returnNode.Value.Value, _currentFunctionReturnType); -// if (returnType == null) return; -// -// if (_currentFunctionReturnType == null) -// { -// ReportError("Cannot return a value from a function with no return type", returnNode.Value.Value); -// return; -// } -// -// if (!NubType.IsCompatibleWith(returnType, _currentFunctionReturnType)) -// { -// ReportError($"Return value of type '{returnType}' is not compatible with function return type '{_currentFunctionReturnType}'", returnNode.Value.Value); -// } -// } -// else if (_currentFunctionReturnType != null) -// { -// ReportError($"Function must return a value of type '{_currentFunctionReturnType}'", returnNode); -// } -// } -// -// private static void CheckDereferenceAssignment(DereferenceAssignmentNode dereferenceAssignment) -// { -// var dereferenceType = CheckExpression(dereferenceAssignment.Dereference); -// if (dereferenceType == null) return; -// var valueType = CheckExpression(dereferenceAssignment.Value, dereferenceType); -// if (valueType == null) return; -// -// if (!NubType.IsCompatibleWith(dereferenceType, valueType)) -// { -// ReportError($"'{valueType}' is not assignable to type '{dereferenceType}'", dereferenceAssignment); -// } -// } -// -// private static NubType? CheckExpression(ExpressionNode expression, NubType? expectedType = null) -// { -// var resultType = expression switch -// { -// AddressOfNode addressOf => CheckAddressOf(addressOf), -// AnonymousFuncNode anonymousFunc => CheckAnonymousFunc(anonymousFunc), -// ArrayIndexAccessNode arrayIndex => CheckArrayIndex(arrayIndex), -// ArrayInitializerNode arrayInitializer => CheckArrayInitializer(arrayInitializer), -// LiteralNode literal => CheckLiteral(literal, expectedType), -// IdentifierNode identifier => CheckIdentifier(identifier), -// BinaryExpressionNode binaryExpr => CheckBinaryExpression(binaryExpr), -// DereferenceNode dereference => CheckDereference(dereference), -// FixedArrayInitializerNode fixedArray => CheckFixedInitializerArray(fixedArray), -// FuncCallNode funcCallExpr => CheckFuncCall(funcCallExpr), -// StructInitializerNode structInit => CheckStructInitializer(structInit), -// UnaryExpressionNode unaryExpression => CheckUnaryExpression(unaryExpression), -// MemberAccessNode memberAccess => CheckMemberAccess(memberAccess), -// _ => throw new UnreachableException() -// }; -// -// if (resultType != null) -// { -// expression.Type = resultType; -// } -// -// return resultType; -// } -// -// private static NubType CheckAnonymousFunc(AnonymousFuncNode anonymousFunc) -// { -// _anonymousFunctions.Enqueue(anonymousFunc); -// return new NubFuncType(anonymousFunc.ReturnType, anonymousFunc.Parameters.Select(p => p.Type).ToList()); -// } -// -// private static NubType? CheckLiteral(LiteralNode literal, NubType? expectedType = null) -// { -// if (expectedType != null) -// { -// if (expectedType.IsNumber && literal.Kind is not LiteralKind.Integer and not LiteralKind.Float) -// { -// ReportError("Expression expects a numeric literal", literal); -// return null; -// } -// -// if (expectedType.IsInteger && literal.Kind == LiteralKind.Float) -// { -// if (literal.Kind == LiteralKind.Float) -// { -// ReportWarning("Float used in integer context. Everything after the '.' will be ignored", literal); -// } -// } -// -// return expectedType; -// } -// -// return literal.Kind switch -// { -// LiteralKind.Integer => NubPrimitiveType.I64, -// LiteralKind.Float => NubPrimitiveType.F64, -// LiteralKind.String => new NubCStringType(), -// LiteralKind.Bool => NubPrimitiveType.Bool, -// _ => throw new ArgumentOutOfRangeException() -// }; -// } -// -// private static NubType? CheckArrayIndex(ArrayIndexAccessNode arrayIndexAccess) -// { -// var expressionType = CheckExpression(arrayIndexAccess.Array); -// if (expressionType == null) return null; -// var indexType = CheckExpression(arrayIndexAccess.Index, NubPrimitiveType.U64); -// if (indexType is { IsInteger: false }) -// { -// ReportError("Array index type must be a number", arrayIndexAccess.Index); -// } -// -// if (expressionType is NubArrayType arrayType) -// { -// return arrayType.ElementType; -// } -// -// if (expressionType is NubFixedArrayType fixedArrayType) -// { -// return fixedArrayType.ElementType; -// } -// -// ReportError($"Cannot access index of non-array type {expressionType}", arrayIndexAccess.Array); -// return null; -// } -// -// private static NubType CheckArrayInitializer(ArrayInitializerNode arrayInitializer) -// { -// var capacityType = CheckExpression(arrayInitializer.Capacity, NubPrimitiveType.U64); -// if (capacityType is { IsInteger: false }) -// { -// ReportError("Array capacity type must be an integer", arrayInitializer.Capacity); -// } -// -// return new NubArrayType(arrayInitializer.ElementType); -// } -// -// private static NubType? CheckIdentifier(IdentifierNode identifier) -// { -// var definition = _definitionTable.LookupFunc(identifier.Namespace.Or(_syntaxTree.Namespace), identifier.Name); -// if (definition.HasValue) -// { -// return new NubFuncType(definition.Value.ReturnType, definition.Value.Parameters.Select(p => p.Type).ToList()); -// } -// -// if (!identifier.Namespace.HasValue) -// { -// return _variables[identifier.Name]; -// } -// -// ReportError($"Identifier '{identifier}' not found", identifier); -// return null; -// } -// -// private static NubType? CheckAddressOf(AddressOfNode addressOf) -// { -// var exprType = CheckExpression(addressOf.Expression); -// if (exprType == null) return null; -// -// return new NubPointerType(exprType); -// } -// -// private static NubType? CheckBinaryExpression(BinaryExpressionNode binaryExpr) -// { -// var leftType = CheckExpression(binaryExpr.Left); -// var rightType = CheckExpression(binaryExpr.Right); -// -// if (leftType == null || rightType == null) return null; -// -// if (!leftType.Equals(rightType)) -// { -// ReportError($"Left '{leftType}' and right '{rightType}' side of the binary expression must be the same type", binaryExpr); -// return null; -// } -// -// switch (binaryExpr.Operator) -// { -// case BinaryExpressionOperator.Equal: -// case BinaryExpressionOperator.NotEqual: -// return NubPrimitiveType.Bool; -// case BinaryExpressionOperator.GreaterThan: -// case BinaryExpressionOperator.GreaterThanOrEqual: -// case BinaryExpressionOperator.LessThan: -// case BinaryExpressionOperator.LessThanOrEqual: -// if (!IsNumeric(leftType)) -// { -// ReportError($"Comparison operators require numeric operands, got '{leftType}' and '{rightType}'", binaryExpr); -// return null; -// } -// -// return NubPrimitiveType.Bool; -// case BinaryExpressionOperator.Plus: -// case BinaryExpressionOperator.Minus: -// case BinaryExpressionOperator.Multiply: -// case BinaryExpressionOperator.Divide: -// if (!IsNumeric(leftType)) -// { -// ReportError($"Arithmetic operators require numeric operands, got '{leftType}' and '{rightType}'", binaryExpr); -// return null; -// } -// -// return leftType; -// default: -// ReportError($"Unsupported binary operator: {binaryExpr.Operator}", binaryExpr); -// return null; -// } -// } -// -// private static NubType? CheckStructInitializer(StructInitializerNode structInit) -// { -// var initialized = new HashSet(); -// -// var defOpt = _definitionTable.LookupStruct(structInit.StructType.Namespace, structInit.StructType.Name); -// if (!defOpt.TryGetValue(out var definition)) -// { -// ReportError($"Struct type '{structInit.StructType.Name}' is not defined", structInit); -// return null; -// } -// -// foreach (var initializer in structInit.Initializers) -// { -// var definitionField = definition.Fields.FirstOrDefault(f => f.Name == initializer.Key); -// if (definitionField == null) -// { -// ReportError($"Field '{initializer.Key}' does not exist in struct '{structInit.StructType.Name}'", initializer.Value); -// continue; -// } -// -// var initializerType = CheckExpression(initializer.Value, definitionField.Type); -// if (initializerType != null && !NubType.IsCompatibleWith(initializerType, definitionField.Type)) -// { -// ReportError($"Cannot initialize field '{initializer.Key}' of type '{definitionField.Type}' with expression of type '{initializerType}'", initializer.Value); -// } -// -// initialized.Add(initializer.Key); -// } -// -// foreach (var field in definition.Fields.Where(f => f.Value.HasValue)) -// { -// initialized.Add(field.Name); -// } -// -// foreach (var field in definition.Fields) -// { -// if (!initialized.Contains(field.Name)) -// { -// ReportError($"Struct field '{field.Name}' is not initialized on type '{structInit.StructType.Name}'", structInit); -// } -// } -// -// return structInit.StructType; -// } -// -// private static NubType? CheckUnaryExpression(UnaryExpressionNode unaryExpression) -// { -// var operandType = CheckExpression(unaryExpression.Operand); -// if (operandType == null) return null; -// -// switch (unaryExpression.Operator) -// { -// case UnaryExpressionOperator.Negate: -// { -// if (operandType.Equals(NubPrimitiveType.I8) || -// operandType.Equals(NubPrimitiveType.I16) || -// operandType.Equals(NubPrimitiveType.I32) || -// operandType.Equals(NubPrimitiveType.I64) || -// operandType.Equals(NubPrimitiveType.F32) || -// operandType.Equals(NubPrimitiveType.F64)) -// { -// return operandType; -// } -// -// ReportError($"Cannot negate non-numeric type {operandType}", unaryExpression.Operand); -// return null; -// } -// case UnaryExpressionOperator.Invert: -// { -// if (!operandType.Equals(NubPrimitiveType.Bool)) -// { -// ReportError($"Cannot invert non-boolean type {operandType}", unaryExpression.Operand); -// return null; -// } -// -// return operandType; -// } -// default: -// { -// ReportError($"Unsupported unary operator: {unaryExpression.Operator}", unaryExpression); -// return null; -// } -// } -// } -// -// private static NubType? CheckMemberAccess(MemberAccessNode memberAccess) -// { -// var expressionType = CheckExpression(memberAccess.Expression); -// if (expressionType == null) return null; -// -// switch (expressionType) -// { -// case NubArrayType: -// { -// if (memberAccess.Member == "count") -// { -// return NubPrimitiveType.I64; -// } -// -// break; -// } -// case NubStructType structType: -// { -// var defOpt = _definitionTable.LookupStruct(structType.Namespace, structType.Name); -// if (!defOpt.TryGetValue(out var definition)) -// { -// ReportError($"Struct type '{structType.Name}' is not defined", memberAccess); -// return null; -// } -// -// var field = definition.Fields.FirstOrDefault(f => f.Name == memberAccess.Member); -// if (field == null) -// { -// ReportError($"Field '{memberAccess.Member}' does not exist in struct '{structType.Name}'", memberAccess); -// return null; -// } -// -// return field.Type; -// } -// } -// -// ReportError($"Cannot access member '{memberAccess.Member}' on type '{expressionType}'", memberAccess); -// return null; -// } -// -// private static void ReportError(string message, Node node) -// { -// var diagnostic = Diagnostic.Error(message).At(node).Build(); -// _diagnostics.Add(diagnostic); -// } -// -// private static void ReportWarning(string message, Node node) -// { -// var diagnostic = Diagnostic.Warning(message).At(node).Build(); -// _diagnostics.Add(diagnostic); -// } -// -// private static bool IsNumeric(NubType type) -// { -// if (type is not NubPrimitiveType primitiveType) -// { -// return false; -// } -// -// switch (primitiveType.Kind) -// { -// case PrimitiveTypeKind.I8: -// case PrimitiveTypeKind.I16: -// case PrimitiveTypeKind.I32: -// case PrimitiveTypeKind.I64: -// case PrimitiveTypeKind.U8: -// case PrimitiveTypeKind.U16: -// case PrimitiveTypeKind.U32: -// case PrimitiveTypeKind.U64: -// case PrimitiveTypeKind.F32: -// case PrimitiveTypeKind.F64: -// return true; -// default: -// return false; -// } -// } -// } \ No newline at end of file