Anon funcs works
This commit is contained in:
@@ -13,8 +13,8 @@ public sealed class Binder
|
||||
private readonly DefinitionTable _definitionTable;
|
||||
|
||||
// TODO: Implement proper variable tracking and scoping
|
||||
private Dictionary<string, NubType> _variables = new();
|
||||
private NubType? _functionReturnType;
|
||||
private readonly Dictionary<string, NubType> _variables = [];
|
||||
private readonly Stack<NubType> _funcReturnTypes = [];
|
||||
|
||||
public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable)
|
||||
{
|
||||
@@ -24,8 +24,8 @@ public sealed class Binder
|
||||
|
||||
public BoundSyntaxTree Bind()
|
||||
{
|
||||
_variables = [];
|
||||
_functionReturnType = null;
|
||||
_variables.Clear();
|
||||
_funcReturnTypes.Clear();
|
||||
|
||||
var diagnostics = new List<Diagnostic>();
|
||||
var definitions = new List<BoundDefinition>();
|
||||
@@ -63,17 +63,18 @@ public sealed class Binder
|
||||
_variables.Clear();
|
||||
var functions = new List<BoundTraitFuncImpl>();
|
||||
|
||||
foreach (var function in node.Functions)
|
||||
foreach (var func in node.Functions)
|
||||
{
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
var signature = BindFuncSignature(func.Signature);
|
||||
|
||||
foreach (var parameter in function.Parameters)
|
||||
foreach (var parameter in signature.Parameters)
|
||||
{
|
||||
_variables[parameter.Name] = parameter.Type;
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, parameter.Type));
|
||||
}
|
||||
|
||||
functions.Add(new BoundTraitFuncImpl(function.Tokens, function.Name, parameters, function.ReturnType, BindBlock(function.Body)));
|
||||
var body = BindFuncBody(func.Body, signature.ReturnType);
|
||||
|
||||
functions.Add(new BoundTraitFuncImpl(func.Tokens, func.Name, signature, body));
|
||||
}
|
||||
|
||||
return new BoundTraitImpl(node.Tokens, node.Namespace, node.TraitType, node.ForType, functions);
|
||||
@@ -85,14 +86,7 @@ public sealed class Binder
|
||||
|
||||
foreach (var function in node.Functions)
|
||||
{
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
|
||||
foreach (var parameter in function.Parameters)
|
||||
{
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, parameter.Type));
|
||||
}
|
||||
|
||||
functions.Add(new BoundTraitFunc(node.Tokens, function.Name, parameters, function.ReturnType));
|
||||
functions.Add(new BoundTraitFunc(node.Tokens, function.Name, BindFuncSignature(function.Signature)));
|
||||
}
|
||||
|
||||
return new BoundTrait(node.Tokens, node.Namespace, node.Name, functions);
|
||||
@@ -119,44 +113,23 @@ public sealed class Binder
|
||||
|
||||
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
||||
{
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
|
||||
foreach (var parameter in node.Parameters)
|
||||
{
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, parameter.Type));
|
||||
}
|
||||
|
||||
return new BoundExternFunc(node.Tokens, node.Namespace, node.Name, node.CallName, parameters, node.ReturnType);
|
||||
return new BoundExternFunc(node.Tokens, node.Namespace, node.Name, node.CallName, BindFuncSignature(node.Signature));
|
||||
}
|
||||
|
||||
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
||||
{
|
||||
_variables.Clear();
|
||||
_functionReturnType = node.ReturnType;
|
||||
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
var signature = BindFuncSignature(node.Signature);
|
||||
|
||||
foreach (var parameter in node.Parameters)
|
||||
foreach (var parameter in signature.Parameters)
|
||||
{
|
||||
_variables[parameter.Name] = parameter.Type;
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, parameter.Type));
|
||||
}
|
||||
|
||||
var body = BindBlock(node.Body);
|
||||
var body = BindFuncBody(node.Body, signature.ReturnType);
|
||||
|
||||
return new BoundLocalFunc(node.Tokens, node.Namespace, node.Name, parameters, body, node.ReturnType);
|
||||
}
|
||||
|
||||
private BoundBlock BindBlock(BlockSyntax node)
|
||||
{
|
||||
var statements = new List<BoundStatement>();
|
||||
|
||||
foreach (var statement in node.Statements)
|
||||
{
|
||||
statements.Add(BindStatement(statement));
|
||||
}
|
||||
|
||||
return new BoundBlock(node.Tokens, statements);
|
||||
return new BoundLocalFunc(node.Tokens, node.Namespace, node.Name, signature, body);
|
||||
}
|
||||
|
||||
private BoundStatement BindStatement(StatementSyntax node)
|
||||
@@ -214,7 +187,7 @@ public sealed class Binder
|
||||
|
||||
if (statement.Value.HasValue)
|
||||
{
|
||||
value = BindExpression(statement.Value.Value, _functionReturnType);
|
||||
value = BindExpression(statement.Value.Value, _funcReturnTypes.Peek());
|
||||
}
|
||||
|
||||
return new BoundReturn(statement.Tokens, value);
|
||||
@@ -262,7 +235,7 @@ public sealed class Binder
|
||||
return node switch
|
||||
{
|
||||
AddressOfSyntax expression => BindAddressOf(expression),
|
||||
AnonymousFuncSyntax expression => BindAnonymousFunc(expression),
|
||||
AnonymousFuncSyntax expression => BindAnonymousFunc(expression, expectedType),
|
||||
ArrayIndexAccessSyntax expression => BindArrayIndexAccess(expression),
|
||||
ArrayInitializerSyntax expression => BindArrayInitializer(expression),
|
||||
BinaryExpressionSyntax expression => BindBinaryExpression(expression),
|
||||
@@ -283,18 +256,37 @@ public sealed class Binder
|
||||
return new BoundAddressOf(expression.Tokens, new NubPointerType(inner.Type), inner);
|
||||
}
|
||||
|
||||
private BoundAnonymousFunc BindAnonymousFunc(AnonymousFuncSyntax expression)
|
||||
private BoundAnonymousFunc BindAnonymousFunc(AnonymousFuncSyntax expression, NubType? expectedType = null)
|
||||
{
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
|
||||
foreach (var parameter in expression.Parameters)
|
||||
if (expectedType == null)
|
||||
{
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, parameter.Type));
|
||||
throw new BindException(Diagnostic.Error("Cannot infer argument types for anonymous function").At(expression).Build());
|
||||
}
|
||||
|
||||
var body = BindBlock(expression.Body);
|
||||
if (expectedType is not NubFuncType funcType)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Expected {expectedType}, but got anonymous function").At(expression).Build());
|
||||
}
|
||||
|
||||
return new BoundAnonymousFunc(expression.Tokens, new NubFuncType(expression.ReturnType, parameters.Select(x => x.Type).ToList()), parameters, body, expression.ReturnType);
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
|
||||
for (var i = 0; i < expression.Parameters.Count; i++)
|
||||
{
|
||||
if (i >= funcType.Parameters.Count)
|
||||
{
|
||||
throw new BindException(Diagnostic.Error($"Anonymous function expected a maximum of {funcType.Parameters.Count} arguments").Build());
|
||||
}
|
||||
|
||||
var expectedParameterType = funcType.Parameters[i];
|
||||
var parameter = expression.Parameters[i];
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, expectedParameterType));
|
||||
|
||||
_variables[parameter.Name] = expectedParameterType;
|
||||
}
|
||||
|
||||
var body = BindFuncBody(expression.Body, funcType.ReturnType);
|
||||
|
||||
return new BoundAnonymousFunc(expression.Tokens, new NubFuncType(funcType.ReturnType, parameters.Select(x => x.Type).ToList()), parameters, funcType.ReturnType, body);
|
||||
}
|
||||
|
||||
private BoundArrayIndexAccess BindArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||
@@ -359,7 +351,7 @@ public sealed class Binder
|
||||
|
||||
var localFunc = localFuncs[0];
|
||||
|
||||
var type = new NubFuncType(localFunc.ReturnType, localFunc.Parameters.Select(p => p.Type).ToList());
|
||||
var type = new NubFuncType(localFunc.Signature.ReturnType, localFunc.Signature.Parameters.Select(p => p.Type).ToList());
|
||||
return new BoundLocalFuncIdent(expression.Tokens, type, @namespace, expression.Name);
|
||||
}
|
||||
|
||||
@@ -373,7 +365,7 @@ public sealed class Binder
|
||||
|
||||
var externFunc = externFuncs[0];
|
||||
|
||||
var type = new NubFuncType(externFunc.ReturnType, externFunc.Parameters.Select(p => p.Type).ToList());
|
||||
var type = new NubFuncType(externFunc.Signature.ReturnType, externFunc.Signature.Parameters.Select(p => p.Type).ToList());
|
||||
return new BoundExternFuncIdent(expression.Tokens, type, @namespace, expression.Name);
|
||||
}
|
||||
|
||||
@@ -413,7 +405,7 @@ public sealed class Binder
|
||||
|
||||
var impl = traitFuncImpls[0];
|
||||
|
||||
var type = new NubFuncType(impl.ReturnType, impl.Parameters.Select(p => p.Type).ToList());
|
||||
var type = new NubFuncType(impl.Signature.ReturnType, impl.Signature.Parameters.Select(p => p.Type).ToList());
|
||||
return new BoundTraitImplFuncAccess(expression.Tokens, type, boundExpression, expression.Member);
|
||||
}
|
||||
|
||||
@@ -439,7 +431,7 @@ public sealed class Binder
|
||||
|
||||
var traitFunc = traitFuncs[0];
|
||||
|
||||
var type = new NubFuncType(traitFunc.ReturnType, traitFunc.Parameters.Select(p => p.Type).ToList());
|
||||
var type = new NubFuncType(traitFunc.Signature.ReturnType, traitFunc.Signature.Parameters.Select(p => p.Type).ToList());
|
||||
return new BoundTraitFuncAccess(expression.Tokens, type, customType, boundExpression, expression.Member);
|
||||
}
|
||||
}
|
||||
@@ -551,6 +543,18 @@ public sealed class Binder
|
||||
return new BoundUnaryExpression(expression.Tokens, type, BindBinaryOperator(expression.Operator), boundOperand);
|
||||
}
|
||||
|
||||
private BoundFuncSignature BindFuncSignature(FuncSignatureSyntax node)
|
||||
{
|
||||
var parameters = new List<BoundFuncParameter>();
|
||||
|
||||
foreach (var parameter in node.Parameters)
|
||||
{
|
||||
parameters.Add(new BoundFuncParameter(parameter.Tokens, parameter.Name, parameter.Type));
|
||||
}
|
||||
|
||||
return new BoundFuncSignature(node.Tokens, parameters, node.ReturnType);
|
||||
}
|
||||
|
||||
private BoundBinaryOperator BindBinaryOperator(BinaryOperator op)
|
||||
{
|
||||
return op switch
|
||||
@@ -578,6 +582,26 @@ public sealed class Binder
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(op), op, null)
|
||||
};
|
||||
}
|
||||
|
||||
private BoundBlock BindBlock(BlockSyntax node)
|
||||
{
|
||||
var statements = new List<BoundStatement>();
|
||||
|
||||
foreach (var statement in node.Statements)
|
||||
{
|
||||
statements.Add(BindStatement(statement));
|
||||
}
|
||||
|
||||
return new BoundBlock(node.Tokens, statements);
|
||||
}
|
||||
|
||||
private BoundBlock BindFuncBody(BlockSyntax block, NubType returnType)
|
||||
{
|
||||
_funcReturnTypes.Push(returnType);
|
||||
var body = BindBlock(block);
|
||||
_funcReturnTypes.Pop();
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
||||
public class BindException : Exception
|
||||
|
||||
Reference in New Issue
Block a user