From 9f988860f92973b4429e6f0899df3974358ba5bc Mon Sep 17 00:00:00 2001 From: nub31 Date: Sun, 22 Jun 2025 20:22:01 +0200 Subject: [PATCH] Binder almost complete --- src/Syntax/Typing/Binder.cs | 148 +++++++++++++++++++++++++----------- 1 file changed, 103 insertions(+), 45 deletions(-) diff --git a/src/Syntax/Typing/Binder.cs b/src/Syntax/Typing/Binder.cs index df72194..c11bbdb 100644 --- a/src/Syntax/Typing/Binder.cs +++ b/src/Syntax/Typing/Binder.cs @@ -1,6 +1,7 @@ using Common; using Syntax.Parsing; using Syntax.Parsing.Node; +using Syntax.Tokenization; using Syntax.Typing.BoundNode; using UnaryExpressionNode = Syntax.Parsing.Node.UnaryExpressionNode; @@ -10,6 +11,7 @@ public static class Binder { private static SyntaxTree _syntaxTree = null!; private static DefinitionTable _definitionTable = null!; + private static NubType? _funcReturnType = null; private static Dictionary _variables = new(); @@ -17,8 +19,11 @@ public static class Binder { _syntaxTree = syntaxTree; _definitionTable = definitionTable; + + _variables = []; + var definitions = new List(); - + foreach (var definition in syntaxTree.Definitions) { definitions.Add(BindDefinition(definition)); @@ -37,20 +42,32 @@ public static class Binder _ => throw new ArgumentOutOfRangeException(nameof(node)) }; } - + private static BoundStructDefinitionNode BindStruct(StructDefinitionNode node) { - var structFields = new List(); + var defOpt = _definitionTable.LookupStruct(node.Namespace, node.Name); + if (!defOpt.TryGetValue(out var definition)) + { + throw new NotImplementedException("Diagnostics not implemented"); + } + var structFields = new List(); + foreach (var structField in node.Fields) { var value = Optional.Empty(); if (structField.Value.HasValue) { - value = BindExpression(structField.Value.Value); + var definitionField = definition.Fields.FirstOrDefault(f => f.Name == structField.Name); + if (definitionField == null) + { + throw new NotImplementedException("Diagnostics not implemented"); + } + + value = BindExpression(structField.Value.Value, definitionField.Type); } - + structFields.Add(new BoundStructField(structField.Name, structField.Type, value)); } @@ -60,21 +77,22 @@ public static class Binder private static BoundExternFuncDefinitionNode BindExternFuncDefinition(ExternFuncDefinitionNode node) { var parameters = new List(); - + foreach (var parameter in node.Parameters) { parameters.Add(new BoundFuncParameter(parameter.Name, parameter.Type)); } - + return new BoundExternFuncDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Name, node.CallName, parameters, node.ReturnType); } private static BoundLocalFuncDefinitionNode BindLocalFuncDefinition(LocalFuncDefinitionNode node) { _variables.Clear(); + _funcReturnType = node.ReturnType; var parameters = new List(); - + foreach (var parameter in node.Parameters) { parameters.Add(new BoundFuncParameter(parameter.Name, parameter.Type)); @@ -82,14 +100,14 @@ public static class Binder } var body = BindBlock(node.Body); - + return new BoundLocalFuncDefinitionNode(node.Tokens, node.Documentation, node.Namespace, node.Name, parameters, body, node.ReturnType, node.Exported); } private static BoundBlockNode BindBlock(BlockNode node) { var statements = new List(); - + foreach (var statement in node.Statements) { statements.Add(BindStatement(statement)); @@ -119,7 +137,9 @@ public static class Binder private static BoundArrayIndexAssignmentNode BindArrayIndex(ArrayIndexAssignmentNode statement) { - return new BoundArrayIndexAssignmentNode(statement.Tokens, BindArrayIndexAccess(statement.ArrayIndexAccess), BindExpression(statement.Value)); + var boundArrayIndex = BindArrayIndexAccess(statement.ArrayIndexAccess); + var elementType = ((NubArrayType)boundArrayIndex.Type).ElementType; + return new BoundArrayIndexAssignmentNode(statement.Tokens, boundArrayIndex, BindExpression(statement.Value, elementType)); } private static BoundBreakNode BindBreak(BreakNode statement) @@ -134,7 +154,9 @@ public static class Binder private static BoundDereferenceAssignmentNode BindDereferenceAssignment(DereferenceAssignmentNode statement) { - return new BoundDereferenceAssignmentNode(statement.Tokens, BindDereference(statement.Dereference), BindExpression(statement.Value)); + var boundDereference = BindDereference(statement.Dereference); + var dereferenceBaseType = ((NubPointerType)boundDereference.Type).BaseType; + return new BoundDereferenceAssignmentNode(statement.Tokens, boundDereference, BindExpression(statement.Value, dereferenceBaseType)); } private static BoundIfNode BindIf(IfNode statement) @@ -149,13 +171,15 @@ public static class Binder @else => BindBlock(@else) ); } - - return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition), BindBlock(statement.Body), elseStatement); + + return new BoundIfNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body), elseStatement); } private static BoundMemberAssignmentNode BindMemberAssignment(MemberAssignmentNode statement) { - return new BoundMemberAssignmentNode(statement.Tokens, BindMemberAccess(statement.MemberAccess), BindExpression(statement.Value)); + var boundMemberAccess = BindMemberAccess(statement.MemberAccess); + var elementType = ((NubArrayType)boundMemberAccess.Type).ElementType; + return new BoundMemberAssignmentNode(statement.Tokens, boundMemberAccess, BindExpression(statement.Value, elementType)); } private static BoundReturnNode BindReturn(ReturnNode statement) @@ -164,7 +188,7 @@ public static class Binder if (statement.Value.HasValue) { - value = BindExpression(statement.Value.Value); + value = BindExpression(statement.Value.Value, _funcReturnType); } return new BoundReturnNode(statement.Tokens, value); @@ -177,7 +201,8 @@ public static class Binder private static BoundVariableAssignmentNode BindVariableAssignment(VariableAssignmentNode statement) { - return new BoundVariableAssignmentNode(statement.Tokens, BindIdentifier(statement.Identifier), BindExpression(statement.Value)); + var variableType = _variables[statement.Identifier.Name]; + return new BoundVariableAssignmentNode(statement.Tokens, BindIdentifier(statement.Identifier), BindExpression(statement.Value, variableType)); } private static BoundVariableDeclarationNode BindVariableDeclaration(VariableDeclarationNode statement) @@ -188,10 +213,10 @@ public static class Binder private static BoundWhileNode BindWhile(WhileNode statement) { - return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition), BindBlock(statement.Body)); + return new BoundWhileNode(statement.Tokens, BindExpression(statement.Condition, NubPrimitiveType.Bool), BindBlock(statement.Body)); } - private static BoundExpressionNode BindExpression(ExpressionNode node) + private static BoundExpressionNode BindExpression(ExpressionNode node, NubType? expectedType = null) { return node switch { @@ -204,7 +229,7 @@ public static class Binder FixedArrayInitializerNode expression => BindFixedArrayInitializer(expression), FuncCallNode expression => BindFuncCall(expression), IdentifierNode expression => BindIdentifier(expression), - LiteralNode expression => BindLiteral(expression), + LiteralNode expression => BindLiteral(expression, expectedType), MemberAccessNode expression => BindMemberAccess(expression), StructInitializerNode expression => BindStructInitializer(expression), UnaryExpressionNode expression => BindUnaryExpression(expression), @@ -222,7 +247,7 @@ public static class Binder { var parameters = new List(); var parameterTypes = new List(); - + foreach (var parameter in expression.Parameters) { var boundParameter = new BoundFuncParameter(parameter.Name, parameter.Type); @@ -239,18 +264,18 @@ public static class Binder { var boundArray = BindExpression(expression.Array); var elementType = ((NubArrayType)boundArray.Type).ElementType; - return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index)); + return new BoundArrayIndexAccessNode(expression.Tokens, elementType, boundArray, BindExpression(expression.Index, NubPrimitiveType.U64)); } private static BoundArrayInitializerNode BindArrayInitializer(ArrayInitializerNode expression) { - return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity), expression.ElementType); + return new BoundArrayInitializerNode(expression.Tokens, new NubArrayType(expression.ElementType), BindExpression(expression.Capacity, NubPrimitiveType.U64), expression.ElementType); } private static BoundBinaryExpressionNode BindBinaryExpression(BinaryExpressionNode expression) { var boundLeft = BindExpression(expression.Left); - var boundRight = BindExpression(expression.Right); + var boundRight = BindExpression(expression.Right, boundLeft.Type); return new BoundBinaryExpressionNode(expression.Tokens, boundLeft.Type, boundLeft, expression.Operator, boundRight); } @@ -269,23 +294,31 @@ public static class Binder private static BoundFuncCallNode BindFuncCall(FuncCallNode expression) { var boundExpression = BindExpression(expression.Expression); - + + var funcType = (NubFuncType)boundExpression.Type; var returnType = ((NubFuncType)boundExpression.Type).ReturnType; - + var parameters = new List(); - - foreach (var parameter in expression.Parameters) + + foreach (var (i, parameter) in expression.Parameters.Index()) { - parameters.Add(BindExpression(parameter)); + if (i >= funcType.Parameters.Count) + { + throw new NotImplementedException("Diagnostics not implemented"); + } + + var expectedType = funcType.Parameters[i]; + + parameters.Add(BindExpression(parameter, expectedType)); } - + return new BoundFuncCallNode(expression.Tokens, returnType, boundExpression, parameters); } private static BoundIdentifierNode BindIdentifier(IdentifierNode expression) { NubType? type = null; - + var definition = _definitionTable.LookupFunc(expression.Namespace.Or(_syntaxTree.Namespace), expression.Name); if (definition.HasValue) { @@ -301,21 +334,30 @@ public static class Binder { throw new NotImplementedException("Diagnostics not implemented"); } - + return new BoundIdentifierNode(expression.Tokens, type, expression.Namespace, expression.Name); } - private static BoundLiteralNode BindLiteral(LiteralNode expression) + private static BoundLiteralNode BindLiteral(LiteralNode expression, NubType? expectedType = null) { - throw new NotImplementedException("Literal requires context"); + var type = expectedType ?? expression.Kind switch + { + LiteralKind.Integer => NubPrimitiveType.I64, + LiteralKind.Float => NubPrimitiveType.F64, + LiteralKind.String => new NubCStringType(), + LiteralKind.Bool => NubPrimitiveType.Bool, + _ => throw new ArgumentOutOfRangeException() + }; + + return new BoundLiteralNode(expression.Tokens, type, expression.Literal, expression.Kind); } private static BoundMemberAccessNode BindMemberAccess(MemberAccessNode expression) { var boundExpression = BindExpression(expression.Expression); - + NubType? type = null; - + switch (boundExpression.Type) { case NubArrayType: @@ -350,41 +392,57 @@ public static class Binder { throw new NotImplementedException("Diagnostics not implemented"); } - + return new BoundMemberAccessNode(expression.Tokens, type, boundExpression, expression.Member); } private static BoundStructInitializerNode BindStructInitializer(StructInitializerNode expression) { - var initializers = new Dictionary(); - - foreach (var (member, initializer) in expression.Initializers) + var defOpt = _definitionTable.LookupStruct(expression.StructType.Namespace, expression.StructType.Name); + if (!defOpt.TryGetValue(out var definition)) { - initializers[member] = BindExpression(initializer); + throw new NotImplementedException("Diagnostics not implemented"); } + var initializers = new Dictionary(); + + foreach (var (member, initializer) in expression.Initializers) + { + var definitionField = definition.Fields.FirstOrDefault(x => x.Name == member); + if (definitionField == null) + { + throw new NotImplementedException("Diagnostics not implemented"); + } + + initializers[member] = BindExpression(initializer, definitionField.Type); + } + return new BoundStructInitializerNode(expression.Tokens, expression.StructType, expression.StructType, initializers); } private static BoundUnaryExpressionNode BindUnaryExpression(UnaryExpressionNode expression) { var boundOperand = BindExpression(expression.Operand); - + NubType? type = null; - + switch (expression.Operator) { case UnaryExpressionOperator.Negate: { + boundOperand = BindExpression(expression.Operand, NubPrimitiveType.I64); + if (boundOperand.Type.IsNumber) { type = boundOperand.Type; } - + break; } case UnaryExpressionOperator.Invert: { + boundOperand = BindExpression(expression.Operand, NubPrimitiveType.Bool); + type = new NubPrimitiveType(PrimitiveTypeKind.Bool); break; } @@ -397,4 +455,4 @@ public static class Binder return new BoundUnaryExpressionNode(expression.Tokens, type, expression.Operator, boundOperand); } -} +} \ No newline at end of file