Anon funcs works
This commit is contained in:
@@ -1,39 +1,52 @@
|
|||||||
struct name
|
// struct name
|
||||||
{
|
// {
|
||||||
first: cstring
|
// first: cstring
|
||||||
last: cstring
|
// last: cstring
|
||||||
}
|
// }
|
||||||
|
|
||||||
struct human
|
// struct human
|
||||||
{
|
// {
|
||||||
name: name
|
// name: name
|
||||||
age: i64
|
// age: i64
|
||||||
}
|
// }
|
||||||
|
|
||||||
trait printable
|
// trait printable
|
||||||
{
|
// {
|
||||||
func print()
|
// func print()
|
||||||
}
|
// }
|
||||||
|
|
||||||
impl printable for human
|
// impl printable for human
|
||||||
{
|
// {
|
||||||
func print() {
|
// func print() {
|
||||||
c::puts(this.name.first)
|
// c::puts(this.name.first)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
func main(args: []cstring): i64
|
func main(args: []cstring): i64
|
||||||
{
|
{
|
||||||
let human = alloc human
|
// let human = alloc human
|
||||||
{
|
// {
|
||||||
name = alloc name {
|
// name = alloc name {
|
||||||
first = "john"
|
// first = "john"
|
||||||
last = "doe"
|
// last = "doe"
|
||||||
}
|
// }
|
||||||
age = 23
|
// age = 23
|
||||||
}
|
// }
|
||||||
|
|
||||||
human.print()
|
// human.print()
|
||||||
|
|
||||||
|
print_result(12, func(num) { return num == 12 })
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func print_result(num: u64, delegate: func(u64): bool) {
|
||||||
|
if (delegate(num))
|
||||||
|
{
|
||||||
|
c::puts("true")
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c::puts("false")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -232,8 +232,8 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private Val EmitLocalFuncIdent(BoundLocalFuncIdent localFuncIdent)
|
private Val EmitLocalFuncIdent(BoundLocalFuncIdent localFuncIdent)
|
||||||
{
|
{
|
||||||
var func = _definitionTable.LookupExternFunc(localFuncIdent.Namespace, localFuncIdent.Name);
|
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Namespace, localFuncIdent.Name);
|
||||||
return new Val(ExternFuncName(func), localFuncIdent.Type, ValKind.Direct);
|
return new Val(LocalFuncName(func), localFuncIdent.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitVariableIdent(BoundVariableIdent variableIdent)
|
private Val EmitVariableIdent(BoundVariableIdent variableIdent)
|
||||||
|
|||||||
@@ -67,19 +67,19 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
foreach (var funcDef in _syntaxTree.Definitions.OfType<BoundLocalFunc>())
|
foreach (var funcDef in _syntaxTree.Definitions.OfType<BoundLocalFunc>())
|
||||||
{
|
{
|
||||||
EmitFuncDefinition(funcDef, LocalFuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body);
|
EmitFuncDefinition(LocalFuncName(funcDef), funcDef.Signature.Parameters, funcDef.Signature.ReturnType, funcDef.Body);
|
||||||
_writer.NewLine();
|
_writer.NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (_anonymousFunctions.TryDequeue(out var anon))
|
while (_anonymousFunctions.TryDequeue(out var anon))
|
||||||
{
|
{
|
||||||
EmitFuncDefinition(anon.Func, anon.Name, anon.Func.Parameters, anon.Func.ReturnType, anon.Func.Body);
|
EmitFuncDefinition(anon.Name, anon.Func.Parameters, anon.Func.ReturnType, anon.Func.Body);
|
||||||
_writer.NewLine();
|
_writer.NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var (impl, name) in _implFunctions)
|
foreach (var (impl, name) in _implFunctions)
|
||||||
{
|
{
|
||||||
EmitFuncDefinition(impl, name, impl.Parameters, impl.ReturnType, impl.Body);
|
EmitFuncDefinition(name, impl.Signature.Parameters, impl.Signature.ReturnType, impl.Body);
|
||||||
_writer.NewLine();
|
_writer.NewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,8 +347,10 @@ public partial class QBEGenerator
|
|||||||
return "l";
|
return "l";
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitFuncDefinition(BoundNode debugNode, string name, List<BoundFuncParameter> parameters, NubType returnType, BoundBlock body)
|
private void EmitFuncDefinition(string name, IEnumerable<BoundFuncParameter> parameters, NubType returnType, BoundBlock body)
|
||||||
{
|
{
|
||||||
|
var parameterArray = parameters.ToArray();
|
||||||
|
|
||||||
_variables.Clear();
|
_variables.Clear();
|
||||||
_variableScopes.Clear();
|
_variableScopes.Clear();
|
||||||
_labelIndex = 0;
|
_labelIndex = 0;
|
||||||
@@ -364,14 +366,13 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
builder.Append(name);
|
builder.Append(name);
|
||||||
|
|
||||||
var parameterStrings = parameters.Select(x => FuncQBETypeName(x.Type) + $" %{x.Name}");
|
var parameterStrings = parameterArray.Select(x => FuncQBETypeName(x.Type) + $" %{x.Name}");
|
||||||
|
|
||||||
builder.Append($"({string.Join(", ", parameterStrings)})");
|
builder.Append($"({string.Join(", ", parameterStrings)})");
|
||||||
|
|
||||||
_writer.StartFunction(builder.ToString());
|
_writer.StartFunction(builder.ToString());
|
||||||
_writer.WriteDebugLocation(debugNode);
|
|
||||||
|
|
||||||
var parameterVars = parameters.Select(parameter => new Variable(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct))).ToList();
|
var parameterVars = parameterArray.Select(parameter => new Variable(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct))).ToList();
|
||||||
|
|
||||||
EmitBlock(body, parameterVars);
|
EmitBlock(body, parameterVars);
|
||||||
|
|
||||||
@@ -438,7 +439,7 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
foreach (var func in traitDef.Functions)
|
foreach (var func in traitDef.Functions)
|
||||||
{
|
{
|
||||||
_writer.Indented($"l, # func {func.Name}({string.Join(", ", func.Parameters.Select(x => $"{x.Name}: {x.Type}"))}): {func.ReturnType}");
|
_writer.Indented($"l, # func {func.Name}({string.Join(", ", func.Signature.Parameters.Select(x => $"{x.Name}: {x.Type}"))}): {func.Signature.ReturnType}");
|
||||||
}
|
}
|
||||||
|
|
||||||
_writer.WriteLine("}");
|
_writer.WriteLine("}");
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ public sealed class Binder
|
|||||||
private readonly DefinitionTable _definitionTable;
|
private readonly DefinitionTable _definitionTable;
|
||||||
|
|
||||||
// TODO: Implement proper variable tracking and scoping
|
// TODO: Implement proper variable tracking and scoping
|
||||||
private Dictionary<string, NubType> _variables = new();
|
private readonly Dictionary<string, NubType> _variables = [];
|
||||||
private NubType? _functionReturnType;
|
private readonly Stack<NubType> _funcReturnTypes = [];
|
||||||
|
|
||||||
public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable)
|
public Binder(SyntaxTree syntaxTree, DefinitionTable definitionTable)
|
||||||
{
|
{
|
||||||
@@ -24,8 +24,8 @@ public sealed class Binder
|
|||||||
|
|
||||||
public BoundSyntaxTree Bind()
|
public BoundSyntaxTree Bind()
|
||||||
{
|
{
|
||||||
_variables = [];
|
_variables.Clear();
|
||||||
_functionReturnType = null;
|
_funcReturnTypes.Clear();
|
||||||
|
|
||||||
var diagnostics = new List<Diagnostic>();
|
var diagnostics = new List<Diagnostic>();
|
||||||
var definitions = new List<BoundDefinition>();
|
var definitions = new List<BoundDefinition>();
|
||||||
@@ -63,17 +63,18 @@ public sealed class Binder
|
|||||||
_variables.Clear();
|
_variables.Clear();
|
||||||
var functions = new List<BoundTraitFuncImpl>();
|
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;
|
_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);
|
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)
|
foreach (var function in node.Functions)
|
||||||
{
|
{
|
||||||
var parameters = new List<BoundFuncParameter>();
|
functions.Add(new BoundTraitFunc(node.Tokens, function.Name, BindFuncSignature(function.Signature)));
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundTrait(node.Tokens, node.Namespace, node.Name, functions);
|
return new BoundTrait(node.Tokens, node.Namespace, node.Name, functions);
|
||||||
@@ -119,44 +113,23 @@ public sealed class Binder
|
|||||||
|
|
||||||
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
private BoundExternFunc BindExternFuncDefinition(ExternFuncSyntax node)
|
||||||
{
|
{
|
||||||
var parameters = new List<BoundFuncParameter>();
|
return new BoundExternFunc(node.Tokens, node.Namespace, node.Name, node.CallName, BindFuncSignature(node.Signature));
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
private BoundLocalFunc BindLocalFuncDefinition(LocalFuncSyntax node)
|
||||||
{
|
{
|
||||||
_variables.Clear();
|
_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;
|
_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);
|
return new BoundLocalFunc(node.Tokens, node.Namespace, node.Name, signature, body);
|
||||||
}
|
|
||||||
|
|
||||||
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 BoundStatement BindStatement(StatementSyntax node)
|
private BoundStatement BindStatement(StatementSyntax node)
|
||||||
@@ -214,7 +187,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
if (statement.Value.HasValue)
|
if (statement.Value.HasValue)
|
||||||
{
|
{
|
||||||
value = BindExpression(statement.Value.Value, _functionReturnType);
|
value = BindExpression(statement.Value.Value, _funcReturnTypes.Peek());
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundReturn(statement.Tokens, value);
|
return new BoundReturn(statement.Tokens, value);
|
||||||
@@ -262,7 +235,7 @@ public sealed class Binder
|
|||||||
return node switch
|
return node switch
|
||||||
{
|
{
|
||||||
AddressOfSyntax expression => BindAddressOf(expression),
|
AddressOfSyntax expression => BindAddressOf(expression),
|
||||||
AnonymousFuncSyntax expression => BindAnonymousFunc(expression),
|
AnonymousFuncSyntax expression => BindAnonymousFunc(expression, expectedType),
|
||||||
ArrayIndexAccessSyntax expression => BindArrayIndexAccess(expression),
|
ArrayIndexAccessSyntax expression => BindArrayIndexAccess(expression),
|
||||||
ArrayInitializerSyntax expression => BindArrayInitializer(expression),
|
ArrayInitializerSyntax expression => BindArrayInitializer(expression),
|
||||||
BinaryExpressionSyntax expression => BindBinaryExpression(expression),
|
BinaryExpressionSyntax expression => BindBinaryExpression(expression),
|
||||||
@@ -283,18 +256,37 @@ public sealed class Binder
|
|||||||
return new BoundAddressOf(expression.Tokens, new NubPointerType(inner.Type), inner);
|
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>();
|
if (expectedType == null)
|
||||||
|
|
||||||
foreach (var parameter in expression.Parameters)
|
|
||||||
{
|
{
|
||||||
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)
|
private BoundArrayIndexAccess BindArrayIndexAccess(ArrayIndexAccessSyntax expression)
|
||||||
@@ -359,7 +351,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var localFunc = localFuncs[0];
|
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);
|
return new BoundLocalFuncIdent(expression.Tokens, type, @namespace, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,7 +365,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var externFunc = externFuncs[0];
|
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);
|
return new BoundExternFuncIdent(expression.Tokens, type, @namespace, expression.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,7 +405,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var impl = traitFuncImpls[0];
|
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);
|
return new BoundTraitImplFuncAccess(expression.Tokens, type, boundExpression, expression.Member);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -439,7 +431,7 @@ public sealed class Binder
|
|||||||
|
|
||||||
var traitFunc = traitFuncs[0];
|
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);
|
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);
|
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)
|
private BoundBinaryOperator BindBinaryOperator(BinaryOperator op)
|
||||||
{
|
{
|
||||||
return op switch
|
return op switch
|
||||||
@@ -578,6 +582,26 @@ public sealed class Binder
|
|||||||
_ => throw new ArgumentOutOfRangeException(nameof(op), op, null)
|
_ => 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
|
public class BindException : Exception
|
||||||
|
|||||||
@@ -9,18 +9,20 @@ public abstract record BoundDefinitionMember(IEnumerable<Token> Tokens) : BoundN
|
|||||||
|
|
||||||
public record BoundFuncParameter(IEnumerable<Token> Tokens, string Name, NubType Type) : BoundDefinitionMember(Tokens);
|
public record BoundFuncParameter(IEnumerable<Token> Tokens, string Name, NubType Type) : BoundDefinitionMember(Tokens);
|
||||||
|
|
||||||
public record BoundLocalFunc(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundFuncParameter> Parameters, BoundBlock Body, NubType ReturnType) : BoundDefinition(Tokens, Namespace);
|
public record BoundFuncSignature(IEnumerable<Token> Tokens, IEnumerable<BoundFuncParameter> Parameters, NubType ReturnType) : BoundDefinitionMember(Tokens);
|
||||||
|
|
||||||
public record BoundExternFunc(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<BoundFuncParameter> Parameters, NubType ReturnType) : BoundDefinition(Tokens, Namespace);
|
public record BoundLocalFunc(IEnumerable<Token> Tokens, string Namespace, string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundDefinition(Tokens, Namespace);
|
||||||
|
|
||||||
|
public record BoundExternFunc(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, BoundFuncSignature Signature) : BoundDefinition(Tokens, Namespace);
|
||||||
|
|
||||||
public record BoundStructField(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<BoundExpression> Value) : BoundDefinitionMember(Tokens);
|
public record BoundStructField(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<BoundExpression> Value) : BoundDefinitionMember(Tokens);
|
||||||
|
|
||||||
public record BoundStruct(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundStructField> Fields) : BoundDefinition(Tokens, Namespace);
|
public record BoundStruct(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundStructField> Fields) : BoundDefinition(Tokens, Namespace);
|
||||||
|
|
||||||
public record BoundTraitFunc(IEnumerable<Token> Tokens, string Name, List<BoundFuncParameter> Parameters, NubType ReturnType) : BoundDefinitionMember(Tokens);
|
public record BoundTraitFunc(IEnumerable<Token> Tokens, string Name, BoundFuncSignature Signature) : BoundDefinitionMember(Tokens);
|
||||||
|
|
||||||
public record BoundTrait(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundTraitFunc> Functions) : BoundDefinition(Tokens, Namespace);
|
public record BoundTrait(IEnumerable<Token> Tokens, string Namespace, string Name, List<BoundTraitFunc> Functions) : BoundDefinition(Tokens, Namespace);
|
||||||
|
|
||||||
public record BoundTraitFuncImpl(IEnumerable<Token> Tokens, string Name, List<BoundFuncParameter> Parameters, NubType ReturnType, BoundBlock Body) : BoundDefinitionMember(Tokens);
|
public record BoundTraitFuncImpl(IEnumerable<Token> Tokens, string Name, BoundFuncSignature Signature, BoundBlock Body) : BoundDefinitionMember(Tokens);
|
||||||
|
|
||||||
public record BoundTraitImpl(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<BoundTraitFuncImpl> Functions) : BoundDefinition(Tokens, Namespace);
|
public record BoundTraitImpl(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<BoundTraitFuncImpl> Functions) : BoundDefinition(Tokens, Namespace);
|
||||||
@@ -40,7 +40,7 @@ public record BoundArrayInitializer(IEnumerable<Token> Tokens, NubType Type, Bou
|
|||||||
|
|
||||||
public record BoundArrayIndexAccess(IEnumerable<Token> Tokens, NubType Type, BoundExpression Target, BoundExpression Index) : BoundExpression(Tokens, Type);
|
public record BoundArrayIndexAccess(IEnumerable<Token> Tokens, NubType Type, BoundExpression Target, BoundExpression Index) : BoundExpression(Tokens, Type);
|
||||||
|
|
||||||
public record BoundAnonymousFunc(IEnumerable<Token> Tokens, NubType Type, List<BoundFuncParameter> Parameters, BoundBlock Body, NubType ReturnType) : BoundExpression(Tokens, Type);
|
public record BoundAnonymousFunc(IEnumerable<Token> Tokens, NubType Type, IEnumerable<BoundFuncParameter> Parameters, NubType ReturnType, BoundBlock Body) : BoundExpression(Tokens, Type);
|
||||||
|
|
||||||
public record BoundAddressOf(IEnumerable<Token> Tokens, NubType Type, BoundExpression Expression) : BoundExpression(Tokens, Type);
|
public record BoundAddressOf(IEnumerable<Token> Tokens, NubType Type, BoundExpression Expression) : BoundExpression(Tokens, Type);
|
||||||
|
|
||||||
|
|||||||
@@ -9,18 +9,20 @@ public abstract record DefinitionMemberSyntax(IEnumerable<Token> Tokens) : Synta
|
|||||||
|
|
||||||
public record FuncParameterSyntax(IEnumerable<Token> Tokens, string Name, NubType Type) : DefinitionMemberSyntax(Tokens);
|
public record FuncParameterSyntax(IEnumerable<Token> Tokens, string Name, NubType Type) : DefinitionMemberSyntax(Tokens);
|
||||||
|
|
||||||
public record LocalFuncSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, List<FuncParameterSyntax> Parameters, BlockSyntax Body, NubType ReturnType) : DefinitionSyntax(Tokens, Namespace);
|
public record FuncSignatureSyntax(IEnumerable<Token> Tokens, IEnumerable<FuncParameterSyntax> Parameters, NubType ReturnType) : DefinitionMemberSyntax(Tokens);
|
||||||
|
|
||||||
public record ExternFuncSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, List<FuncParameterSyntax> Parameters, NubType ReturnType) : DefinitionSyntax(Tokens, Namespace);
|
public record LocalFuncSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionSyntax(Tokens, Namespace);
|
||||||
|
|
||||||
|
public record ExternFuncSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, string CallName, FuncSignatureSyntax Signature) : DefinitionSyntax(Tokens, Namespace);
|
||||||
|
|
||||||
public record StructFieldSyntax(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<ExpressionSyntax> Value) : DefinitionMemberSyntax(Tokens);
|
public record StructFieldSyntax(IEnumerable<Token> Tokens, int Index, string Name, NubType Type, Optional<ExpressionSyntax> Value) : DefinitionMemberSyntax(Tokens);
|
||||||
|
|
||||||
public record StructSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Namespace);
|
public record StructSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, List<StructFieldSyntax> Fields) : DefinitionSyntax(Tokens, Namespace);
|
||||||
|
|
||||||
public record TraitFuncSyntax(IEnumerable<Token> Tokens, string Name, List<FuncParameterSyntax> Parameters, NubType ReturnType) : DefinitionMemberSyntax(Tokens);
|
public record TraitFuncSyntax(IEnumerable<Token> Tokens, string Name, FuncSignatureSyntax Signature) : DefinitionMemberSyntax(Tokens);
|
||||||
|
|
||||||
public record TraitSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, List<TraitFuncSyntax> Functions) : DefinitionSyntax(Tokens, Namespace);
|
public record TraitSyntax(IEnumerable<Token> Tokens, string Namespace, string Name, List<TraitFuncSyntax> Functions) : DefinitionSyntax(Tokens, Namespace);
|
||||||
|
|
||||||
public record TraitFuncImplSyntax(IEnumerable<Token> Tokens, string Name, List<FuncParameterSyntax> Parameters, NubType ReturnType, BlockSyntax Body) : DefinitionMemberSyntax(Tokens);
|
public record TraitFuncImplSyntax(IEnumerable<Token> Tokens, string Name, FuncSignatureSyntax Signature, BlockSyntax Body) : DefinitionMemberSyntax(Tokens);
|
||||||
|
|
||||||
public record TraitImplSyntax(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<TraitFuncImplSyntax> Functions) : DefinitionSyntax(Tokens, Namespace);
|
public record TraitImplSyntax(IEnumerable<Token> Tokens, string Namespace, NubType TraitType, NubType ForType, List<TraitFuncImplSyntax> Functions) : DefinitionSyntax(Tokens, Namespace);
|
||||||
@@ -37,7 +37,9 @@ public record ArrayInitializerSyntax(IEnumerable<Token> Tokens, ExpressionSyntax
|
|||||||
|
|
||||||
public record ArrayIndexAccessSyntax(IEnumerable<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
|
public record ArrayIndexAccessSyntax(IEnumerable<Token> Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record AnonymousFuncSyntax(IEnumerable<Token> Tokens, List<FuncParameterSyntax> Parameters, BlockSyntax Body, NubType ReturnType) : ExpressionSyntax(Tokens);
|
public record AnonymousFuncParameterSyntax(IEnumerable<Token> Tokens, string Name) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
public record AnonymousFuncSyntax(IEnumerable<Token> Tokens, List<AnonymousFuncParameterSyntax> Parameters, BlockSyntax Body) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
public record AddressOfSyntax(IEnumerable<Token> Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens);
|
public record AddressOfSyntax(IEnumerable<Token> Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens);
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ public sealed class Parser
|
|||||||
private readonly IEnumerable<Token> _tokens;
|
private readonly IEnumerable<Token> _tokens;
|
||||||
|
|
||||||
private readonly List<Diagnostic> _diagnostics = [];
|
private readonly List<Diagnostic> _diagnostics = [];
|
||||||
private NubType? _functionReturnType;
|
|
||||||
private int _tokenIndex;
|
private int _tokenIndex;
|
||||||
|
|
||||||
public Parser(IEnumerable<Token> tokens)
|
public Parser(IEnumerable<Token> tokens)
|
||||||
@@ -24,7 +23,6 @@ public sealed class Parser
|
|||||||
public SyntaxTree Parse()
|
public SyntaxTree Parse()
|
||||||
{
|
{
|
||||||
_diagnostics.Clear();
|
_diagnostics.Clear();
|
||||||
_functionReturnType = null;
|
|
||||||
_tokenIndex = 0;
|
_tokenIndex = 0;
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Namespace))
|
if (TryExpectSymbol(Symbol.Namespace))
|
||||||
@@ -61,7 +59,7 @@ public sealed class Parser
|
|||||||
Symbol.Func => ParseFunc(startIndex),
|
Symbol.Func => ParseFunc(startIndex),
|
||||||
Symbol.Struct => ParseStruct(startIndex),
|
Symbol.Struct => ParseStruct(startIndex),
|
||||||
Symbol.Trait => ParseTrait(startIndex),
|
Symbol.Trait => ParseTrait(startIndex),
|
||||||
Symbol.Impl => ParseImplementation(startIndex),
|
Symbol.Impl => ParseImpl(startIndex),
|
||||||
_ => throw new ParseException(Diagnostic
|
_ => throw new ParseException(Diagnostic
|
||||||
.Error($"Expected 'func' or 'struct', but found '{keyword.Symbol}'")
|
.Error($"Expected 'func' or 'struct', but found '{keyword.Symbol}'")
|
||||||
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
.WithHelp("Valid definition keywords are 'func' and 'struct'")
|
||||||
@@ -72,6 +70,48 @@ public sealed class Parser
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FuncSignatureSyntax ParseFuncSignature(FuncParameterSyntax? thisArg = null)
|
||||||
|
{
|
||||||
|
var startIndex = _tokenIndex;
|
||||||
|
|
||||||
|
List<FuncParameterSyntax> parameters = [];
|
||||||
|
|
||||||
|
if (thisArg != null)
|
||||||
|
{
|
||||||
|
parameters.Add(thisArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpectSymbol(Symbol.OpenParen);
|
||||||
|
|
||||||
|
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||||
|
{
|
||||||
|
parameters.Add(ParseFuncParameter());
|
||||||
|
|
||||||
|
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
||||||
|
{
|
||||||
|
_diagnostics.Add(Diagnostic
|
||||||
|
.Warning("Missing comma between function parameters")
|
||||||
|
.WithHelp("Add a ',' to separate parameters")
|
||||||
|
.At(token)
|
||||||
|
.Build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
||||||
|
|
||||||
|
return new FuncSignatureSyntax(GetTokens(startIndex), parameters, returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FuncParameterSyntax ParseFuncParameter()
|
||||||
|
{
|
||||||
|
var startIndex = _tokenIndex;
|
||||||
|
var name = ExpectIdentifier();
|
||||||
|
ExpectSymbol(Symbol.Colon);
|
||||||
|
var type = ParseType();
|
||||||
|
|
||||||
|
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
|
||||||
|
}
|
||||||
|
|
||||||
private DefinitionSyntax ParseExtern(int startIndex)
|
private DefinitionSyntax ParseExtern(int startIndex)
|
||||||
{
|
{
|
||||||
var keyword = ExpectSymbol();
|
var keyword = ExpectSymbol();
|
||||||
@@ -85,25 +125,6 @@ public sealed class Parser
|
|||||||
private ExternFuncSyntax ParseExternFunc(int startIndex)
|
private ExternFuncSyntax ParseExternFunc(int startIndex)
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
List<FuncParameterSyntax> parameters = [];
|
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
|
||||||
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
|
||||||
{
|
|
||||||
parameters.Add(ParseFuncParameter());
|
|
||||||
|
|
||||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
|
||||||
{
|
|
||||||
_diagnostics.Add(Diagnostic
|
|
||||||
.Warning("Missing comma between function parameters")
|
|
||||||
.WithHelp("Add a ',' to separate parameters")
|
|
||||||
.At(token)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
|
||||||
var callName = name.Value;
|
var callName = name.Value;
|
||||||
|
|
||||||
if (TryExpectSymbol(Symbol.Calls))
|
if (TryExpectSymbol(Symbol.Calls))
|
||||||
@@ -111,36 +132,18 @@ public sealed class Parser
|
|||||||
callName = ExpectIdentifier().Value;
|
callName = ExpectIdentifier().Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, parameters, returnType);
|
var signature = ParseFuncSignature();
|
||||||
|
|
||||||
|
return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
private LocalFuncSyntax ParseFunc(int startIndex)
|
private LocalFuncSyntax ParseFunc(int startIndex)
|
||||||
{
|
{
|
||||||
var name = ExpectIdentifier();
|
var name = ExpectIdentifier();
|
||||||
List<FuncParameterSyntax> parameters = [];
|
var signature = ParseFuncSignature();
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
|
||||||
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
|
||||||
{
|
|
||||||
parameters.Add(ParseFuncParameter());
|
|
||||||
|
|
||||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
|
||||||
{
|
|
||||||
_diagnostics.Add(Diagnostic
|
|
||||||
.Warning("Missing comma between function parameters")
|
|
||||||
.WithHelp("Add a ',' to separate parameters")
|
|
||||||
.At(token)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
|
||||||
_functionReturnType = returnType;
|
|
||||||
|
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
|
|
||||||
return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, parameters, body, returnType);
|
return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, signature, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private StructSyntax ParseStruct(int startIndex)
|
private StructSyntax ParseStruct(int startIndex)
|
||||||
@@ -189,32 +192,15 @@ public sealed class Parser
|
|||||||
ExpectSymbol(Symbol.Func);
|
ExpectSymbol(Symbol.Func);
|
||||||
|
|
||||||
var funcName = ExpectIdentifier().Value;
|
var funcName = ExpectIdentifier().Value;
|
||||||
var parameters = new List<FuncParameterSyntax>();
|
var signature = ParseFuncSignature();
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
functions.Add(new TraitFuncSyntax(GetTokens(funcStartIndex), funcName, signature));
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
|
||||||
{
|
|
||||||
var parameter = ParseFuncParameter();
|
|
||||||
parameters.Add(parameter);
|
|
||||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
|
|
||||||
{
|
|
||||||
_diagnostics.Add(Diagnostic
|
|
||||||
.Warning("Missing comma between function arguments")
|
|
||||||
.WithHelp("Add a ',' to separate arguments")
|
|
||||||
.At(nextToken)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
|
||||||
|
|
||||||
functions.Add(new TraitFuncSyntax(GetTokens(funcStartIndex), funcName, parameters, returnType));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TraitSyntax(GetTokens(startIndex), _namespace, name, functions);
|
return new TraitSyntax(GetTokens(startIndex), _namespace, name, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TraitImplSyntax ParseImplementation(int startIndex)
|
private TraitImplSyntax ParseImpl(int startIndex)
|
||||||
{
|
{
|
||||||
var traitType = ParseType();
|
var traitType = ParseType();
|
||||||
ExpectSymbol(Symbol.For);
|
ExpectSymbol(Symbol.For);
|
||||||
@@ -228,47 +214,16 @@ public sealed class Parser
|
|||||||
var funcStartIndex = _tokenIndex;
|
var funcStartIndex = _tokenIndex;
|
||||||
ExpectSymbol(Symbol.Func);
|
ExpectSymbol(Symbol.Func);
|
||||||
var functionName = ExpectIdentifier().Value;
|
var functionName = ExpectIdentifier().Value;
|
||||||
var parameters = new List<FuncParameterSyntax>
|
|
||||||
{
|
|
||||||
new([], "this", forType)
|
|
||||||
};
|
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
|
||||||
|
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
|
||||||
{
|
|
||||||
parameters.Add(ParseFuncParameter());
|
|
||||||
|
|
||||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var token) && token is not SymbolToken { Symbol: Symbol.CloseParen })
|
|
||||||
{
|
|
||||||
_diagnostics.Add(Diagnostic
|
|
||||||
.Warning("Missing comma between function parameters")
|
|
||||||
.WithHelp("Add a ',' to separate parameters")
|
|
||||||
.At(token)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
|
||||||
|
|
||||||
|
var signature = ParseFuncSignature(new FuncParameterSyntax([], "this", forType));
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
|
|
||||||
functions.AddRange(new TraitFuncImplSyntax(GetTokens(funcStartIndex), functionName, parameters, returnType, body));
|
functions.AddRange(new TraitFuncImplSyntax(GetTokens(funcStartIndex), functionName, signature, body));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new TraitImplSyntax(GetTokens(startIndex), _namespace, traitType, forType, functions);
|
return new TraitImplSyntax(GetTokens(startIndex), _namespace, traitType, forType, functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FuncParameterSyntax ParseFuncParameter()
|
|
||||||
{
|
|
||||||
var startIndex = _tokenIndex;
|
|
||||||
var name = ExpectIdentifier();
|
|
||||||
ExpectSymbol(Symbol.Colon);
|
|
||||||
var type = ParseType();
|
|
||||||
|
|
||||||
return new FuncParameterSyntax(GetTokens(startIndex), name.Value, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private StatementSyntax ParseStatement()
|
private StatementSyntax ParseStatement()
|
||||||
{
|
{
|
||||||
var startIndex = _tokenIndex;
|
var startIndex = _tokenIndex;
|
||||||
@@ -353,7 +308,8 @@ public sealed class Parser
|
|||||||
ExpectSymbol(Symbol.Return);
|
ExpectSymbol(Symbol.Return);
|
||||||
|
|
||||||
var value = Optional<ExpressionSyntax>.Empty();
|
var value = Optional<ExpressionSyntax>.Empty();
|
||||||
if (_functionReturnType is not NubVoidType)
|
|
||||||
|
if (!TryExpectSymbol(Symbol.Semi))
|
||||||
{
|
{
|
||||||
value = ParseExpression();
|
value = ParseExpression();
|
||||||
}
|
}
|
||||||
@@ -500,27 +456,18 @@ public sealed class Parser
|
|||||||
{
|
{
|
||||||
case Symbol.Func:
|
case Symbol.Func:
|
||||||
{
|
{
|
||||||
List<FuncParameterSyntax> parameters = [];
|
List<AnonymousFuncParameterSyntax> parameters = [];
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
ExpectSymbol(Symbol.OpenParen);
|
||||||
while (!TryExpectSymbol(Symbol.CloseParen))
|
while (!TryExpectSymbol(Symbol.CloseParen))
|
||||||
{
|
{
|
||||||
var parameter = ParseFuncParameter();
|
var parameterStartIndex = _tokenIndex;
|
||||||
parameters.Add(parameter);
|
var name = ExpectIdentifier();
|
||||||
if (!TryExpectSymbol(Symbol.Comma) && Peek().TryGetValue(out var nextToken) && nextToken is not SymbolToken { Symbol: Symbol.CloseParen })
|
parameters.Add(new AnonymousFuncParameterSyntax(GetTokens(parameterStartIndex), name.Value));
|
||||||
{
|
|
||||||
_diagnostics.Add(Diagnostic
|
|
||||||
.Warning("Missing comma between function arguments")
|
|
||||||
.WithHelp("Add a ',' to separate arguments")
|
|
||||||
.At(nextToken)
|
|
||||||
.Build());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType();
|
|
||||||
|
|
||||||
var body = ParseBlock();
|
var body = ParseBlock();
|
||||||
|
|
||||||
expr = new AnonymousFuncSyntax(GetTokens(startIndex), parameters, body, returnType);
|
expr = new AnonymousFuncSyntax(GetTokens(startIndex), parameters, body);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Symbol.OpenParen:
|
case Symbol.OpenParen:
|
||||||
|
|||||||
@@ -70,5 +70,6 @@ public enum Symbol
|
|||||||
Trait,
|
Trait,
|
||||||
Impl,
|
Impl,
|
||||||
For,
|
For,
|
||||||
Extern
|
Extern,
|
||||||
|
Semi
|
||||||
}
|
}
|
||||||
@@ -55,6 +55,7 @@ public sealed class Tokenizer
|
|||||||
['!'] = Symbol.Bang,
|
['!'] = Symbol.Bang,
|
||||||
['^'] = Symbol.Caret,
|
['^'] = Symbol.Caret,
|
||||||
['&'] = Symbol.Ampersand,
|
['&'] = Symbol.Ampersand,
|
||||||
|
[';'] = Symbol.Semi,
|
||||||
};
|
};
|
||||||
|
|
||||||
private readonly SourceText _sourceText;
|
private readonly SourceText _sourceText;
|
||||||
|
|||||||
Reference in New Issue
Block a user