Binder almost complete
This commit is contained in:
@@ -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<string, NubType> _variables = new();
|
||||
|
||||
@@ -17,8 +19,11 @@ public static class Binder
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
_definitionTable = definitionTable;
|
||||
|
||||
_variables = [];
|
||||
|
||||
var definitions = new List<BoundDefinitionNode>();
|
||||
|
||||
|
||||
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<BoundStructField>();
|
||||
var defOpt = _definitionTable.LookupStruct(node.Namespace, node.Name);
|
||||
if (!defOpt.TryGetValue(out var definition))
|
||||
{
|
||||
throw new NotImplementedException("Diagnostics not implemented");
|
||||
}
|
||||
|
||||
var structFields = new List<BoundStructField>();
|
||||
|
||||
foreach (var structField in node.Fields)
|
||||
{
|
||||
var value = Optional.Empty<BoundExpressionNode>();
|
||||
|
||||
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<BoundFuncParameter>();
|
||||
|
||||
|
||||
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<BoundFuncParameter>();
|
||||
|
||||
|
||||
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<BoundStatementNode>();
|
||||
|
||||
|
||||
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<BoundFuncParameter>();
|
||||
var parameterTypes = new List<NubType>();
|
||||
|
||||
|
||||
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<BoundExpressionNode>();
|
||||
|
||||
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<string, BoundExpressionNode>();
|
||||
|
||||
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<string, BoundExpressionNode>();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user