diff --git a/example/src/main.nub b/example/src/main.nub index 5dc53c4..1037aa0 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -34,7 +34,7 @@ func main(args: []cstring): i64 } human.print() - print_result(12, func(num) { return num == 12 }) + print_result(12, func (num) => num == 12) let x: cstring = "test" diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.Expression.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.Expression.cs index 007e2a5..f39e1ea 100644 --- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.Expression.cs +++ b/src/compiler/NubLang/Generation/QBE/QBEGenerator.Expression.cs @@ -17,7 +17,7 @@ public partial class QBEGenerator BoundStructInitializer structInitializer => EmitStructInitializer(structInitializer), BoundAddressOf addressOf => EmitAddressOf(addressOf), BoundDereference dereference => EmitDereference(dereference), - BoundAnonymousFunc anonymousFunc => EmitAnonymousFunc(anonymousFunc), + BoundArrowFunc arrowFunc => EmitArrowFunc(arrowFunc), BoundBinaryExpression binaryExpression => EmitBinaryExpression(binaryExpression), BoundFuncCall funcCallExpression => EmitFuncCall(funcCallExpression), BoundExternFuncIdent externFuncIdent => EmitExternFuncIdent(externFuncIdent), @@ -33,11 +33,11 @@ public partial class QBEGenerator }; } - private Val EmitAnonymousFunc(BoundAnonymousFunc anonymousFunc) + private Val EmitArrowFunc(BoundArrowFunc arrowFunc) { - var name = $"$anon_func{++_anonymousFuncIndex}"; - _anonymousFunctions.Enqueue((anonymousFunc, name)); - return new Val(name, anonymousFunc.Type, ValKind.Direct); + var name = $"$arrow_func{++_arrowFuncIndex}"; + _arrowFunctions.Enqueue((arrowFunc, name)); + return new Val(name, arrowFunc.Type, ValKind.Direct); } private Val EmitArrayIndexAccess(BoundArrayIndexAccess arrayIndexAccess) diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs index 418a997..9d99d04 100644 --- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -16,12 +16,12 @@ public partial class QBEGenerator private readonly List _stringLiterals = []; private readonly Stack _breakLabels = []; private readonly Stack _continueLabels = []; - private readonly Queue<(BoundAnonymousFunc Func, string Name)> _anonymousFunctions = []; + private readonly Queue<(BoundArrowFunc Func, string Name)> _arrowFunctions = []; private readonly Dictionary _implFunctions = []; private readonly Stack _scopes = []; private int _tmpIndex; private int _labelIndex; - private int _anonymousFuncIndex; + private int _arrowFuncIndex; private int _cStringLiteralIndex; private int _stringLiteralIndex; private int _implFuncNameIndex; @@ -42,12 +42,12 @@ public partial class QBEGenerator _stringLiterals.Clear(); _breakLabels.Clear(); _continueLabels.Clear(); - _anonymousFunctions.Clear(); + _arrowFunctions.Clear(); _implFunctions.Clear(); _scopes.Clear(); _tmpIndex = 0; _labelIndex = 0; - _anonymousFuncIndex = 0; + _arrowFuncIndex = 0; _cStringLiteralIndex = 0; _stringLiteralIndex = 0; _implFuncNameIndex = 0; @@ -71,9 +71,9 @@ public partial class QBEGenerator _writer.NewLine(); } - while (_anonymousFunctions.TryDequeue(out var anon)) + while (_arrowFunctions.TryDequeue(out var arrowFunc)) { - EmitFuncDefinition(anon.Name, anon.Func.Parameters, anon.Func.ReturnType, anon.Func.Body); + EmitFuncDefinition(arrowFunc.Name, arrowFunc.Func.Parameters, arrowFunc.Func.ReturnType, arrowFunc.Func.Body); _writer.NewLine(); } diff --git a/src/compiler/NubLang/Syntax/Binding/Binder.cs b/src/compiler/NubLang/Syntax/Binding/Binder.cs index 031c669..6376b35 100644 --- a/src/compiler/NubLang/Syntax/Binding/Binder.cs +++ b/src/compiler/NubLang/Syntax/Binding/Binder.cs @@ -220,7 +220,7 @@ public sealed class Binder return node switch { AddressOfSyntax expression => BindAddressOf(expression), - AnonymousFuncSyntax expression => BindAnonymousFunc(expression, expectedType), + ArrowFuncSyntax expression => BindArrowFunc(expression, expectedType), ArrayIndexAccessSyntax expression => BindArrayIndexAccess(expression), ArrayInitializerSyntax expression => BindArrayInitializer(expression), BinaryExpressionSyntax expression => BindBinaryExpression(expression), @@ -241,16 +241,16 @@ public sealed class Binder return new BoundAddressOf(expression.Tokens, new NubPointerType(inner.Type), inner); } - private BoundAnonymousFunc BindAnonymousFunc(AnonymousFuncSyntax expression, NubType? expectedType = null) + private BoundArrowFunc BindArrowFunc(ArrowFuncSyntax expression, NubType? expectedType = null) { if (expectedType == null) { - throw new BindException(Diagnostic.Error("Cannot infer argument types for anonymous function").At(expression).Build()); + throw new BindException(Diagnostic.Error("Cannot infer argument types for arrow function").At(expression).Build()); } if (expectedType is not NubFuncType funcType) { - throw new BindException(Diagnostic.Error($"Expected {expectedType}, but got anonymous function").At(expression).Build()); + throw new BindException(Diagnostic.Error($"Expected {expectedType}, but got arrow function").At(expression).Build()); } var parameters = new List(); @@ -259,7 +259,7 @@ public sealed class Binder { if (i >= funcType.Parameters.Count) { - throw new BindException(Diagnostic.Error($"Anonymous function expected a maximum of {funcType.Parameters.Count} arguments").Build()); + throw new BindException(Diagnostic.Error($"Arrow function expected a maximum of {funcType.Parameters.Count} arguments").Build()); } var expectedParameterType = funcType.Parameters[i]; @@ -269,7 +269,7 @@ public sealed class Binder var body = BindFuncBody(expression.Body, funcType.ReturnType, parameters); - return new BoundAnonymousFunc(expression.Tokens, new NubFuncType(funcType.ReturnType, parameters.Select(x => x.Type).ToList()), parameters, funcType.ReturnType, body); + return new BoundArrowFunc(expression.Tokens, new NubFuncType(funcType.ReturnType, parameters.Select(x => x.Type).ToList()), parameters, funcType.ReturnType, body); } private BoundArrayIndexAccess BindArrayIndexAccess(ArrayIndexAccessSyntax expression) diff --git a/src/compiler/NubLang/Syntax/Binding/Node/BoundExpression.cs b/src/compiler/NubLang/Syntax/Binding/Node/BoundExpression.cs index cafef37..e218bd5 100644 --- a/src/compiler/NubLang/Syntax/Binding/Node/BoundExpression.cs +++ b/src/compiler/NubLang/Syntax/Binding/Node/BoundExpression.cs @@ -40,7 +40,7 @@ public record BoundArrayInitializer(IReadOnlyList Tokens, NubType Type, B public record BoundArrayIndexAccess(IReadOnlyList Tokens, NubType Type, BoundExpression Target, BoundExpression Index) : BoundExpression(Tokens, Type); -public record BoundAnonymousFunc(IReadOnlyList Tokens, NubType Type, IReadOnlyList Parameters, NubType ReturnType, BoundBlock Body) : BoundExpression(Tokens, Type); +public record BoundArrowFunc(IReadOnlyList Tokens, NubType Type, IReadOnlyList Parameters, NubType ReturnType, BoundBlock Body) : BoundExpression(Tokens, Type); public record BoundAddressOf(IReadOnlyList Tokens, NubType Type, BoundExpression Expression) : BoundExpression(Tokens, Type); diff --git a/src/compiler/NubLang/Syntax/Parsing/Node/ExpressionSyntax.cs b/src/compiler/NubLang/Syntax/Parsing/Node/ExpressionSyntax.cs index 94ea7da..3a7a2bd 100644 --- a/src/compiler/NubLang/Syntax/Parsing/Node/ExpressionSyntax.cs +++ b/src/compiler/NubLang/Syntax/Parsing/Node/ExpressionSyntax.cs @@ -37,9 +37,9 @@ public record ArrayInitializerSyntax(IReadOnlyList Tokens, ExpressionSynt public record ArrayIndexAccessSyntax(IReadOnlyList Tokens, ExpressionSyntax Target, ExpressionSyntax Index) : ExpressionSyntax(Tokens); -public record AnonymousFuncParameterSyntax(IReadOnlyList Tokens, string Name) : ExpressionSyntax(Tokens); +public record ArrowFuncParameterSyntax(IReadOnlyList Tokens, string Name) : ExpressionSyntax(Tokens); -public record AnonymousFuncSyntax(IReadOnlyList Tokens, IReadOnlyList Parameters, BlockSyntax Body) : ExpressionSyntax(Tokens); +public record ArrowFuncSyntax(IReadOnlyList Tokens, IReadOnlyList Parameters, BlockSyntax Body) : ExpressionSyntax(Tokens); public record AddressOfSyntax(IReadOnlyList Tokens, ExpressionSyntax Expression) : ExpressionSyntax(Tokens); diff --git a/src/compiler/NubLang/Syntax/Parsing/Parser.cs b/src/compiler/NubLang/Syntax/Parsing/Parser.cs index 738bbc1..00eb01f 100644 --- a/src/compiler/NubLang/Syntax/Parsing/Parser.cs +++ b/src/compiler/NubLang/Syntax/Parsing/Parser.cs @@ -456,18 +456,31 @@ public sealed class Parser { case Symbol.Func: { - List parameters = []; + List parameters = []; ExpectSymbol(Symbol.OpenParen); while (!TryExpectSymbol(Symbol.CloseParen)) { var parameterStartIndex = _tokenIndex; var name = ExpectIdentifier(); - parameters.Add(new AnonymousFuncParameterSyntax(GetTokens(parameterStartIndex), name.Value)); + parameters.Add(new ArrowFuncParameterSyntax(GetTokens(parameterStartIndex), name.Value)); } - var body = ParseBlock(); + BlockSyntax body; - expr = new AnonymousFuncSyntax(GetTokens(startIndex), parameters, body); + if (TryExpectSymbol(Symbol.Arrow)) + { + var blockStartIndex = _tokenIndex; + var returnValue = ParseExpression(); + var tokens = GetTokens(blockStartIndex); + var arrowExpression = new ReturnSyntax(tokens, returnValue); + body = new BlockSyntax(tokens, [arrowExpression]); + } + else + { + body = ParseBlock(); + } + + expr = new ArrowFuncSyntax(GetTokens(startIndex), parameters, body); break; } case Symbol.OpenParen: diff --git a/src/compiler/NubLang/Syntax/Tokenization/Token.cs b/src/compiler/NubLang/Syntax/Tokenization/Token.cs index 6afd393..08cf2a6 100644 --- a/src/compiler/NubLang/Syntax/Tokenization/Token.cs +++ b/src/compiler/NubLang/Syntax/Tokenization/Token.cs @@ -71,5 +71,6 @@ public enum Symbol Impl, For, Extern, - Semi + Semi, + Arrow, } \ No newline at end of file diff --git a/src/compiler/NubLang/Syntax/Tokenization/Tokenizer.cs b/src/compiler/NubLang/Syntax/Tokenization/Tokenizer.cs index ed60ec5..17885a0 100644 --- a/src/compiler/NubLang/Syntax/Tokenization/Tokenizer.cs +++ b/src/compiler/NubLang/Syntax/Tokenization/Tokenizer.cs @@ -32,6 +32,7 @@ public sealed class Tokenizer [['<', '=']] = Symbol.LessThanOrEqual, [['>', '=']] = Symbol.GreaterThanOrEqual, [[':', ':']] = Symbol.DoubleColon, + [['=', '>']] = Symbol.Arrow, }; private static readonly Dictionary Chars = new()