diff --git a/example/src/main.nub b/example/src/main.nub index 8161698..01ea5f5 100644 --- a/example/src/main.nub +++ b/example/src/main.nub @@ -22,7 +22,7 @@ impl printable for human } } -export func main(args: []cstring): i64 +func main(args: []cstring): i64 { let human = alloc human { diff --git a/src/compiler/NubLang.CLI/assets/libruntime_x64.a b/src/compiler/NubLang.CLI/assets/libruntime_x64.a index d43a568..61d3d14 100644 Binary files a/src/compiler/NubLang.CLI/assets/libruntime_x64.a and b/src/compiler/NubLang.CLI/assets/libruntime_x64.a differ diff --git a/src/compiler/NubLang/Diagnostics/ConsoleColors.cs b/src/compiler/NubLang/Diagnostics/ConsoleColors.cs index 3c9f563..086a46f 100644 --- a/src/compiler/NubLang/Diagnostics/ConsoleColors.cs +++ b/src/compiler/NubLang/Diagnostics/ConsoleColors.cs @@ -71,8 +71,6 @@ public static class ConsoleColors LiteralKind.Bool => Blue, _ => White }; - case ModifierToken: - return White; case SymbolToken symbol: switch (symbol.Symbol) { diff --git a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs index bb4483b..47c481a 100644 --- a/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs +++ b/src/compiler/NubLang/Generation/QBE/QBEGenerator.cs @@ -67,19 +67,19 @@ public partial class QBEGenerator foreach (var funcDef in _syntaxTree.Definitions.OfType()) { - EmitFuncDefinition(funcDef, LocalFuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported); + EmitFuncDefinition(funcDef, LocalFuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body); _writer.NewLine(); } while (_anonymousFunctions.TryDequeue(out var anon)) { - EmitFuncDefinition(anon.Func, anon.Name, anon.Func.Parameters, anon.Func.ReturnType, anon.Func.Body, false); + EmitFuncDefinition(anon.Func, anon.Name, anon.Func.Parameters, anon.Func.ReturnType, anon.Func.Body); _writer.NewLine(); } foreach (var (impl, name) in _implFunctions) { - EmitFuncDefinition(impl, name, impl.Parameters, impl.ReturnType, impl.Body, false); + EmitFuncDefinition(impl, name, impl.Parameters, impl.ReturnType, impl.Body); _writer.NewLine(); } @@ -347,7 +347,7 @@ public partial class QBEGenerator return "l"; } - private void EmitFuncDefinition(BoundNode debugNode, string name, List parameters, NubType returnType, BoundBlock body, bool exported) + private void EmitFuncDefinition(BoundNode debugNode, string name, List parameters, NubType returnType, BoundBlock body) { _variables.Clear(); _variableScopes.Clear(); @@ -356,12 +356,7 @@ public partial class QBEGenerator var builder = new StringBuilder(); - if (exported) - { - builder.Append("export "); - } - - builder.Append("function "); + builder.Append("export function "); if (returnType is not NubVoidType) { builder.Append(FuncQBETypeName(returnType) + ' '); @@ -503,7 +498,7 @@ public partial class QBEGenerator private string LocalFuncName(BoundLocalFunc funcDef) { - return funcDef.Exported ? $"${funcDef.Name}" : $"${funcDef.Namespace}_{funcDef.Name}"; + return $"${funcDef.Namespace}_{funcDef.Name}"; } private string ExternFuncName(BoundExternFunc funcDef) diff --git a/src/compiler/NubLang/Syntax/Binding/Binder.cs b/src/compiler/NubLang/Syntax/Binding/Binder.cs index b05ffae..93a30ee 100644 --- a/src/compiler/NubLang/Syntax/Binding/Binder.cs +++ b/src/compiler/NubLang/Syntax/Binding/Binder.cs @@ -144,7 +144,7 @@ public sealed class Binder var body = BindBlock(node.Body); - return new BoundLocalFunc(node.Tokens, node.Namespace, node.Name, parameters, body, node.ReturnType, node.Exported); + return new BoundLocalFunc(node.Tokens, node.Namespace, node.Name, parameters, body, node.ReturnType); } private BoundBlock BindBlock(BlockSyntax node) diff --git a/src/compiler/NubLang/Syntax/Binding/Node/BoundDefinition.cs b/src/compiler/NubLang/Syntax/Binding/Node/BoundDefinition.cs index ffa3b42..e5327ef 100644 --- a/src/compiler/NubLang/Syntax/Binding/Node/BoundDefinition.cs +++ b/src/compiler/NubLang/Syntax/Binding/Node/BoundDefinition.cs @@ -9,7 +9,7 @@ public abstract record BoundDefinitionMember(IEnumerable Tokens) : BoundN public record BoundFuncParameter(IEnumerable Tokens, string Name, NubType Type) : BoundDefinitionMember(Tokens); -public record BoundLocalFunc(IEnumerable Tokens, string Namespace, string Name, List Parameters, BoundBlock Body, NubType ReturnType, bool Exported) : BoundDefinition(Tokens, Namespace); +public record BoundLocalFunc(IEnumerable Tokens, string Namespace, string Name, List Parameters, BoundBlock Body, NubType ReturnType) : BoundDefinition(Tokens, Namespace); public record BoundExternFunc(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, NubType ReturnType) : BoundDefinition(Tokens, Namespace); diff --git a/src/compiler/NubLang/Syntax/Parsing/Node/DefinitionSyntax.cs b/src/compiler/NubLang/Syntax/Parsing/Node/DefinitionSyntax.cs index ea5978e..1296528 100644 --- a/src/compiler/NubLang/Syntax/Parsing/Node/DefinitionSyntax.cs +++ b/src/compiler/NubLang/Syntax/Parsing/Node/DefinitionSyntax.cs @@ -9,7 +9,7 @@ public abstract record DefinitionMemberSyntax(IEnumerable Tokens) : Synta public record FuncParameterSyntax(IEnumerable Tokens, string Name, NubType Type) : DefinitionMemberSyntax(Tokens); -public record LocalFuncSyntax(IEnumerable Tokens, string Namespace, string Name, List Parameters, BlockSyntax Body, NubType ReturnType, bool Exported) : DefinitionSyntax(Tokens, Namespace); +public record LocalFuncSyntax(IEnumerable Tokens, string Namespace, string Name, List Parameters, BlockSyntax Body, NubType ReturnType) : DefinitionSyntax(Tokens, Namespace); public record ExternFuncSyntax(IEnumerable Tokens, string Namespace, string Name, string CallName, List Parameters, NubType ReturnType) : DefinitionSyntax(Tokens, Namespace); diff --git a/src/compiler/NubLang/Syntax/Parsing/Parser.cs b/src/compiler/NubLang/Syntax/Parsing/Parser.cs index d0e140a..5af4cc3 100644 --- a/src/compiler/NubLang/Syntax/Parsing/Parser.cs +++ b/src/compiler/NubLang/Syntax/Parsing/Parser.cs @@ -17,7 +17,7 @@ public sealed class Parser public Parser(IEnumerable tokens) { - _namespace = "global"; + _namespace = "default"; _tokens = tokens; } @@ -38,7 +38,7 @@ public sealed class Parser { try { - definitions.Add(ParseTopLevel()); + definitions.Add(ParseDefinition()); } catch (ParseException ex) { @@ -50,20 +50,15 @@ public sealed class Parser return new SyntaxTree(_namespace, definitions, _diagnostics); } - private DefinitionSyntax ParseTopLevel() + private DefinitionSyntax ParseDefinition() { var startIndex = _tokenIndex; - List modifiers = []; - - while (TryExpectModifier(out var modifier)) - { - modifiers.Add(modifier); - } var keyword = ExpectSymbol(); var node = keyword.Symbol switch { - Symbol.Func => ParseFunc(startIndex, modifiers), + Symbol.Extern => ParseExtern(startIndex), + Symbol.Func => ParseFunc(startIndex), Symbol.Struct => ParseStruct(startIndex), Symbol.Trait => ParseTrait(startIndex), Symbol.Impl => ParseImplementation(startIndex), @@ -74,19 +69,52 @@ public sealed class Parser .Build()) }; - if (modifiers.Count != 0) - { - throw new ParseException(Diagnostic - .Error($"Invalid modifiers: {string.Join(", ", modifiers.Select(x => x.Modifier))}") - .WithHelp($"Remove the following modifiers: {modifiers.Select(x => x.Modifier)}'") - .At(SourceSpan.Merge(modifiers.Select(x => x.Span))) - .Build()); - } - return node; } - private DefinitionSyntax ParseFunc(int startIndex, List modifiers) + private DefinitionSyntax ParseExtern(int startIndex) + { + var keyword = ExpectSymbol(); + return keyword.Symbol switch + { + Symbol.Func => ParseExternFunc(startIndex), + _ => throw new ParseException(Diagnostic.Error($"Unexpected symbol {keyword.Symbol} after extern declaration").At(keyword).Build()) + }; + } + + private ExternFuncSyntax ParseExternFunc(int startIndex) + { + var name = ExpectIdentifier(); + List 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; + + if (TryExpectSymbol(Symbol.Calls)) + { + callName = ExpectIdentifier().Value; + } + + return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, parameters, returnType); + } + + private LocalFuncSyntax ParseFunc(int startIndex) { var name = ExpectIdentifier(); List parameters = []; @@ -110,32 +138,9 @@ public sealed class Parser var returnType = TryExpectSymbol(Symbol.Colon) ? ParseType() : new NubVoidType(); _functionReturnType = returnType; - var isExtern = modifiers.RemoveAll(x => x.Modifier == Modifier.Extern) > 0; - if (isExtern) - { - if (modifiers.Count != 0) - { - throw new ParseException(Diagnostic - .Error($"Invalid modifier for extern function: {modifiers[0].Modifier}") - .WithHelp($"Extern functions cannot use the '{modifiers[0].Modifier}' modifier") - .At(modifiers[0]) - .Build()); - } - - var callName = name.Value; - - if (TryExpectSymbol(Symbol.Calls)) - { - callName = ExpectIdentifier().Value; - } - - return new ExternFuncSyntax(GetTokens(startIndex), _namespace, name.Value, callName, parameters, returnType); - } - var body = ParseBlock(); - var exported = modifiers.RemoveAll(x => x.Modifier == Modifier.Export) > 0; - return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, parameters, body, returnType, exported); + return new LocalFuncSyntax(GetTokens(startIndex), _namespace, name.Value, parameters, body, returnType); } private StructSyntax ParseStruct(int startIndex) @@ -657,7 +662,7 @@ public sealed class Parser catch (ParseException ex) { _diagnostics.Add(ex.Diagnostic); - RecoverToNextStatement(); + Next(); } } @@ -805,19 +810,6 @@ public sealed class Parser return false; } - private bool TryExpectModifier([NotNullWhen(true)] out ModifierToken? modifier) - { - if (Peek() is { Value: ModifierToken modifierToken }) - { - modifier = modifierToken; - Next(); - return true; - } - - modifier = null; - return false; - } - private bool TryExpectIdentifier([NotNullWhen(true)] out IdentifierToken? identifier) { if (Peek() is { Value: IdentifierToken identifierToken }) @@ -851,23 +843,7 @@ public sealed class Parser while (Peek().HasValue) { var token = Peek().Value; - if (token is SymbolToken { Symbol: Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl } or ModifierToken) - { - break; - } - - Next(); - } - } - - private void RecoverToNextStatement() - { - while (Peek().TryGetValue(out var token)) - { - if (token is SymbolToken { Symbol: Symbol.CloseBrace } or IdentifierToken or SymbolToken - { - Symbol: Symbol.Return or Symbol.If or Symbol.While or Symbol.Let or Symbol.Break or Symbol.Continue - }) + if (token is SymbolToken { Symbol: Symbol.Extern or Symbol.Func or Symbol.Struct or Symbol.Trait or Symbol.Impl }) { break; } diff --git a/src/compiler/NubLang/Syntax/Tokenization/Token.cs b/src/compiler/NubLang/Syntax/Tokenization/Token.cs index 45aebc9..373794f 100644 --- a/src/compiler/NubLang/Syntax/Tokenization/Token.cs +++ b/src/compiler/NubLang/Syntax/Tokenization/Token.cs @@ -24,17 +24,6 @@ public enum LiteralKind Bool } -public class ModifierToken(SourceSpan span, Modifier modifier) : Token(span) -{ - public Modifier Modifier { get; } = modifier; -} - -public enum Modifier -{ - Extern, - Export -} - public class SymbolToken(SourceSpan span, Symbol symbol) : Token(span) { public Symbol Symbol { get; } = symbol; @@ -80,5 +69,6 @@ public enum Symbol Calls, Trait, Impl, - For + For, + Extern } \ 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 b3c0316..9bd064d 100644 --- a/src/compiler/NubLang/Syntax/Tokenization/Tokenizer.cs +++ b/src/compiler/NubLang/Syntax/Tokenization/Tokenizer.cs @@ -22,12 +22,7 @@ public sealed class Tokenizer ["trait"] = Symbol.Trait, ["impl"] = Symbol.Impl, ["for"] = Symbol.For, - }; - - private static readonly Dictionary Modifiers = new() - { - ["export"] = Modifier.Export, - ["extern"] = Modifier.Extern, + ["extern"] = Symbol.Extern }; private static readonly Dictionary Chians = new() @@ -129,11 +124,6 @@ public sealed class Tokenizer return new SymbolToken(CreateSpan(startIndex), keywordSymbol); } - if (Modifiers.TryGetValue(buffer, out var modifer)) - { - return new ModifierToken(CreateSpan(startIndex), modifer); - } - if (buffer is "true" or "false") { return new LiteralToken(CreateSpan(startIndex), LiteralKind.Bool, buffer); diff --git a/src/runtime/targets/x64.s b/src/runtime/targets/x64.s index f55a1d0..68e8922 100644 --- a/src/runtime/targets/x64.s +++ b/src/runtime/targets/x64.s @@ -4,7 +4,7 @@ .globl _start _start: mov rdi, rsp - call main + call default_main mov rdi, rax mov rax, 60 syscall