From 0c3f5ca3bee9b001e462a5e36e8354ebf7c97a7f Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 19 Aug 2024 00:01:36 +0200 Subject: [PATCH 001/109] Syntax --- src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs | 3 + src/Draco.Compiler/Api/Syntax/TokenKind.cs | 15 ++ .../Internal/Declarations/ClassDeclaration.cs | 48 +++++ .../Internal/Symbols/FunctionSymbol.cs | 8 + src/Draco.Compiler/Internal/Syntax/Syntax.xml | 189 ++++++++++++++++++ 5 files changed, 263 insertions(+) create mode 100644 src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs index d51a7bde5..26ed66ea8 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs @@ -18,8 +18,10 @@ public static class SyntaxFacts TokenKind.EndOfInput => string.Empty, TokenKind.InterpolationEnd => "}", TokenKind.KeywordAnd => "and", + TokenKind.KeywordClass => "class", TokenKind.KeywordElse => "else", TokenKind.KeywordFalse => "false", + TokenKind.KeywordField => "field", TokenKind.KeywordFor => "for", TokenKind.KeywordFunc => "func", TokenKind.KeywordGoto => "goto", @@ -36,6 +38,7 @@ public static class SyntaxFacts TokenKind.KeywordReturn => "return", TokenKind.KeywordTrue => "true", TokenKind.KeywordVal => "val", + TokenKind.KeywordValue => "value", TokenKind.KeywordVar => "var", TokenKind.KeywordWhile => "while", TokenKind.ParenOpen => "(", diff --git a/src/Draco.Compiler/Api/Syntax/TokenKind.cs b/src/Draco.Compiler/Api/Syntax/TokenKind.cs index 9c6c533e5..0b5236ad7 100644 --- a/src/Draco.Compiler/Api/Syntax/TokenKind.cs +++ b/src/Draco.Compiler/Api/Syntax/TokenKind.cs @@ -80,6 +80,11 @@ public enum TokenKind /// KeywordAnd, + /// + /// The keyword 'class'. + /// + KeywordClass, + /// /// The keyword 'else'. /// @@ -90,6 +95,11 @@ public enum TokenKind /// KeywordFalse, + /// + /// The keyword 'field'. + /// + KeywordField, + /// /// The keyword 'for'. /// @@ -170,6 +180,11 @@ public enum TokenKind /// KeywordVal, + /// + /// The keyword 'value'. + /// + KeywordValue, + /// /// The keyword 'var'. /// diff --git a/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs new file mode 100644 index 000000000..17f491670 --- /dev/null +++ b/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Draco.Compiler.Api.Syntax; + +namespace Draco.Compiler.Internal.Declarations; + +/// +/// A class declaration. +/// +internal sealed class ClassDeclaration(ClassDeclarationSyntax syntax) : Declaration(syntax.Name.Text) +{ + /// + /// The syntax of the declaration. + /// + public ClassDeclarationSyntax Syntax { get; } = syntax; + + public override ImmutableArray Children => + InterlockedUtils.InitializeDefault(ref this.children, this.BuildChildren); + private ImmutableArray children; + + public override IEnumerable DeclaringSyntaxes + { + get + { + yield return this.Syntax; + } + } + + private ImmutableArray BuildChildren() + { + if (this.Syntax.Body is not BlockClassBodySyntax block) return ImmutableArray.Empty; + + return block.Declarations.Select(this.BuildChild).OfType().ToImmutableArray(); + } + + // TODO: More entries to handle + private Declaration? BuildChild(SyntaxNode node) => node switch + { + // NOTE: We ignore import declarations in the declaration tree, unlike Roslyn + // We handle import declarations during constructing the binders + // Since we allow for imports in local scopes too, this is the most sensible choice + ImportDeclarationSyntax => null, + UnexpectedDeclarationSyntax => null, + _ => throw new ArgumentOutOfRangeException(nameof(node)), + }; +} diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index 062f0f5d1..33cc51755 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -74,6 +74,14 @@ public delegate IOperand CodegenDelegate( _ => throw new System.ArgumentOutOfRangeException(nameof(token)), }; + /// + /// The receiver of this function, if it has one. + /// + public TypeSymbol? Receiver => this.IsStatic + ? null + : this.ContainingSymbol as TypeSymbol; + + /// /// The parameters of this function. /// diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 0c4538da6..e100c5eaf 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -233,6 +233,195 @@ + + + A class declaration. + + + + + The visibility modifier keyword possibly starting the declaration. + + + + + + + + + A modifier for making a class a value-type. + + + + + + + + The 'class' keyword starting the delcaration. + + + + + + + + The name of the declared class. + + + + + + + + The list of generic parameters, in case the class introduces generics. + + + + + + The primary constructor of the class. + + + + + + The body of the class. + + + + + + + A primary constructor declaration. + + + + + The optional visibility modifier keyword of the constructor. + + + + + + + + + The opening parenthesis before the parameter list. + + + + + + + + The parameters this constructor declares. + + + + + + The closing parenthesis after the parameter list. + + + + + + + + + A single parameter declaration in a primary constructor parameter list. + + + + + Optional modifiers for the parameter, in case it is manifested as a member. + + + + + The parameter declaration. + + + + + + + Modifiers for a primary constructor parameter, in case it is manifested as a member. + + + + + The optional visibility modifier keyword of the member. + + + + + + + + The optional field modifier keyword to mark a field instead of a property. + + + + + + + The keyword introducing the variable, either 'var' or 'val'. + + + + + + + + + + A class declaration body. + + + + + + A semicolon-terminated empty class body. + + + + + The semicolon terminating the class body. + + + + + + + + + A block class body with multiple declarations within braces. + + + + + The opening brace token. + + + + + + + + All declaration syntaxes within the class. + + + + + + The closing brace token. + + + + + + A function declaration. From c2ebad116d399b85756db9a4eaa98905690e7344 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 25 Aug 2024 22:39:36 +0200 Subject: [PATCH 002/109] wip --- .../Syntax/ParserTests.cs | 33 +++++++ .../Declarations/SingleModuleDeclaration.cs | 1 + .../Symbols/Source/SourceClassSymbol.cs | 31 ++++++ .../Internal/Symbols/TypeSymbol.cs | 2 +- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 48 +++++----- src/Draco.Compiler/Internal/Syntax/Parser.cs | 96 ++++++++++++++++++- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 90 ----------------- 7 files changed, 182 insertions(+), 119 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs diff --git a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs index 9ab912636..f78ef1493 100644 --- a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs +++ b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs @@ -1823,4 +1823,37 @@ public void TestImportDeclarationWithVisibilityModifier() this.T(TokenKind.Semicolon); } } + + [Fact] + public void TestClassDeclaration() + { + this.ParseDeclaration(""" + class Foo { + } + """); + + this.N(); + { + this.T(TokenKind.KeywordClass); + this.T(TokenKind.Identifier, "Foo"); + this.N(); + } + } + + [Fact] + public void TestValueClassDeclaration() + { + this.ParseDeclaration(""" + value class Foo { + } + """); + + this.N(); + { + this.T(TokenKind.KeywordValue); + this.T(TokenKind.KeywordClass); + this.T(TokenKind.Identifier, "Foo"); + this.N(); + } + } } diff --git a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs index 9211a0841..9131db329 100644 --- a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs @@ -45,6 +45,7 @@ private ImmutableArray BuildChildren() => ImportDeclarationSyntax => null, VariableDeclarationSyntax var => new GlobalDeclaration(var), FunctionDeclarationSyntax func => new FunctionDeclaration(func), + ClassDeclarationSyntax @class => new ClassDeclaration(@class), ModuleDeclarationSyntax module => new SingleModuleDeclaration(module.Name.Text, this.Path.Append(module.Name.Text), module), UnexpectedDeclarationSyntax => null, _ => throw new ArgumentOutOfRangeException(nameof(node)), diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs new file mode 100644 index 000000000..e08cdc07a --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -0,0 +1,31 @@ +using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Binding; + +namespace Draco.Compiler.Internal.Symbols.Source; + +/// +/// A generic class defined in-source. +/// +internal sealed class SourceClassSymbol( + Symbol containingSymbol, + ClassDeclarationSyntax syntax) : TypeSymbol, ISourceSymbol +{ + public override Symbol? ContainingSymbol { get; } = containingSymbol; + public override string Name => this.DeclaringSyntax.Name.Text; + + public override ClassDeclarationSyntax DeclaringSyntax => syntax; + + public void Bind(IBinderProvider binderProvider) + { + this.Bind + } + + + private protected string GenericsToString() + { + if (this.IsGenericDefinition) return $"<{string.Join(", ", this.GenericParameters)}>"; + return string.Empty; + } + + public override string ToString() => $"{this.Name}<{}>; +} diff --git a/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs b/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs index dd3c7f80c..2183bcc47 100644 --- a/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs @@ -161,7 +161,7 @@ private ImmutableArray BuildMembers() .OfType() .FirstOrDefault(f => !f.IsStatic && f.Name == "Invoke"); } - + private ImmutableArray BuildBaseTypes() => GraphTraversal.DepthFirst( start: this, getNeighbors: s => s.ImmediateBaseTypes, diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 33423244f..279253507 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -319,29 +319,31 @@ Unit TakeWithText(TokenKind tokenKind, int length) var ident = this.Advance(offset); // Remap keywords // TODO: Any better/faster way? - var tokenKind = ident switch - { - var _ when ident.Span.SequenceEqual("and") => TokenKind.KeywordAnd, - var _ when ident.Span.SequenceEqual("else") => TokenKind.KeywordElse, - var _ when ident.Span.SequenceEqual("false") => TokenKind.KeywordFalse, - var _ when ident.Span.SequenceEqual("for") => TokenKind.KeywordFor, - var _ when ident.Span.SequenceEqual("func") => TokenKind.KeywordFunc, - var _ when ident.Span.SequenceEqual("goto") => TokenKind.KeywordGoto, - var _ when ident.Span.SequenceEqual("if") => TokenKind.KeywordIf, - var _ when ident.Span.SequenceEqual("import") => TokenKind.KeywordImport, - var _ when ident.Span.SequenceEqual("in") => TokenKind.KeywordIn, - var _ when ident.Span.SequenceEqual("internal") => TokenKind.KeywordInternal, - var _ when ident.Span.SequenceEqual("mod") => TokenKind.KeywordMod, - var _ when ident.Span.SequenceEqual("module") => TokenKind.KeywordModule, - var _ when ident.Span.SequenceEqual("not") => TokenKind.KeywordNot, - var _ when ident.Span.SequenceEqual("or") => TokenKind.KeywordOr, - var _ when ident.Span.SequenceEqual("public") => TokenKind.KeywordPublic, - var _ when ident.Span.SequenceEqual("rem") => TokenKind.KeywordRem, - var _ when ident.Span.SequenceEqual("return") => TokenKind.KeywordReturn, - var _ when ident.Span.SequenceEqual("true") => TokenKind.KeywordTrue, - var _ when ident.Span.SequenceEqual("val") => TokenKind.KeywordVal, - var _ when ident.Span.SequenceEqual("var") => TokenKind.KeywordVar, - var _ when ident.Span.SequenceEqual("while") => TokenKind.KeywordWhile, + var tokenKind = ident.Span switch + { + "and" => TokenKind.KeywordAnd, + "class" => TokenKind.KeywordClass, + "else" => TokenKind.KeywordElse, + "false" => TokenKind.KeywordFalse, + "for" => TokenKind.KeywordFor, + "func" => TokenKind.KeywordFunc, + "goto" => TokenKind.KeywordGoto, + "if" => TokenKind.KeywordIf, + "import" => TokenKind.KeywordImport, + "in" => TokenKind.KeywordIn, + "internal" => TokenKind.KeywordInternal, + "mod" => TokenKind.KeywordMod, + "module" => TokenKind.KeywordModule, + "not" => TokenKind.KeywordNot, + "or" => TokenKind.KeywordOr, + "public" => TokenKind.KeywordPublic, + "rem" => TokenKind.KeywordRem, + "return" => TokenKind.KeywordReturn, + "true" => TokenKind.KeywordTrue, + "val" => TokenKind.KeywordVal, + "value" => TokenKind.KeywordValue, + "var" => TokenKind.KeywordVar, + "while" => TokenKind.KeywordWhile, _ => TokenKind.Identifier, }; // Return the appropriate token diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index e16032f7e..a4b3f52aa 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Draco.Compiler.Api.Diagnostics; +using Draco.Compiler.Api.Semantics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Diagnostics; @@ -248,21 +249,30 @@ internal DeclarationSyntax ParseDeclaration(bool local = false) => /// The parsed . private DeclarationSyntax ParseDeclaration(DeclarationContext context) { - var modifier = this.ParseVisibilityModifier(); + var visibility = this.ParseVisibilityModifier(); switch (this.Peek()) { case TokenKind.KeywordImport: - return this.ParseImportDeclaration(modifier); + return this.ParseImportDeclaration(visibility); + + case TokenKind.KeywordValue: + { + var valueKeyword = this.Expect(TokenKind.KeywordValue); + return this.ParseClassDeclaration(visibility: visibility, valueType: valueKeyword); + } + + case TokenKind.KeywordClass: + return this.ParseClassDeclaration(visibility: visibility, valueType: null); case TokenKind.KeywordFunc: - return this.ParseFunctionDeclaration(modifier); + return this.ParseFunctionDeclaration(visibility); case TokenKind.KeywordModule: return this.ParseModuleDeclaration(context); case TokenKind.KeywordVar: case TokenKind.KeywordVal: - return this.ParseVariableDeclaration(modifier); + return this.ParseVariableDeclaration(visibility); case TokenKind.Identifier when this.Peek(1) == TokenKind.Colon: return this.ParseLabelDeclaration(context); @@ -277,7 +287,7 @@ _ when IsVisibilityModifier(t) => false, }); var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "declaration"); var diag = new SyntaxDiagnosticInfo(info, Offset: 0, Width: input.FullWidth); - var node = new UnexpectedDeclarationSyntax(modifier, input); + var node = new UnexpectedDeclarationSyntax(visibility, input); this.AddDiagnostic(node, diag); return node; } @@ -360,6 +370,82 @@ private ImportPathSyntax ParseImportPath() return result; } + /// + /// Parses a class declaration. + /// + /// Optional visibility modifier token. + /// Optional valuetype modifier token. + /// The parsed . + private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, SyntaxToken? valueType) + { + // Class keyword and name of the class + var classKeyword = this.Expect(TokenKind.KeywordClass); + var name = this.Expect(TokenKind.Identifier); + + // Optional generics + var generics = null as GenericParameterListSyntax; + if (this.Peek() == TokenKind.LessThan) generics = this.ParseGenericParameterList(); + + var body = this.ParseClassBody(); + + return new ClassDeclarationSyntax( + visibility, + valueType, + classKeyword, + name, + generics, + body); + } + + /// + /// Parses the body of a class. + /// + /// The parsed . + private ClassBodySyntax ParseClassBody() + { + switch (this.Peek()) + { + case TokenKind.Semicolon: + return this.ParseEmptyClassBody(); + case TokenKind.CurlyOpen: + return this.ParseBlockClassBody(); + default: + // TODO + throw new NotImplementedException(); + } + } + + /// + /// Parses an empty class body, which is just a semicolon. + /// + /// The parsed . + private EmptyClassBodySyntax ParseEmptyClassBody() + { + var semicolon = this.Expect(TokenKind.Semicolon); + return new EmptyClassBodySyntax(semicolon); + } + + /// + /// Parses a block class body declared with curly braces. + /// + /// The parsed . + private BlockClassBodySyntax ParseBlockClassBody() + { + var openBrace = this.Expect(TokenKind.CurlyOpen); + var decls = SyntaxList.CreateBuilder(); + while (true) + { + // Break on the end of the block + if (this.Peek() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; + + // Parse a declaration + var decl = this.ParseDeclaration(DeclarationContext.Global); + decls.Add(decl); + } + var closeBrace = this.Expect(TokenKind.CurlyClose); + return new(openBrace, decls.ToSyntaxList(), closeBrace); + } + /// /// Parses a . /// diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index e100c5eaf..831bf8581 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -277,12 +277,6 @@ - - - The primary constructor of the class. - - - The body of the class. @@ -290,90 +284,6 @@ - - - A primary constructor declaration. - - - - - The optional visibility modifier keyword of the constructor. - - - - - - - - - The opening parenthesis before the parameter list. - - - - - - - - The parameters this constructor declares. - - - - - - The closing parenthesis after the parameter list. - - - - - - - - - A single parameter declaration in a primary constructor parameter list. - - - - - Optional modifiers for the parameter, in case it is manifested as a member. - - - - - The parameter declaration. - - - - - - - Modifiers for a primary constructor parameter, in case it is manifested as a member. - - - - - The optional visibility modifier keyword of the member. - - - - - - - - The optional field modifier keyword to mark a field instead of a property. - - - - - - - The keyword introducing the variable, either 'var' or 'val'. - - - - - - - A class declaration body. From 451df51619a281df5daa1289fb0c0b66bfeb68e4 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 9 Sep 2024 00:56:14 +0200 Subject: [PATCH 003/109] wip --- .../Semantics/SemanticModelTests.cs | 28 +++++++ .../Api/Syntax/SyntaxFactory.cs | 27 +++++-- .../Symbols/Source/SourceClassSymbol.cs | 76 +++++++++++++++++-- .../Symbols/Source/SourceFieldSymbol.cs | 17 +++++ .../Symbols/Source/SourceFunctionSymbol.cs | 2 +- .../Symbols/Source/SourceModuleSymbol.cs | 2 + 6 files changed, 139 insertions(+), 13 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs diff --git a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs index c0f021d9a..5cd196612 100644 --- a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs @@ -478,4 +478,32 @@ public void GetPathSymbolsFromPartiallyNonExistingImport() Assert.True(nonexistingSymbol.IsError); Assert.True(fooSymbol.IsError); } + + [Fact] + public void GetReferencedSymbolFromSourceClassSymbol() + { + // class Foo { + // func bar() {} + // } + + // Arrange + var tree = SyntaxTree.Create(CompilationUnit(ClassDeclaration( + "Foo", + GenericParameterList(), + [FunctionDeclaration("bar", ParameterList(), null, BlockFunctionBody())] + ))); + var compilation = CreateCompilation(tree); + var classDecl = tree.FindInChildren(0); + Assert.NotNull(classDecl); + + // Act + var semanticModel = compilation.GetSemanticModel(tree); + var classSymbol = GetInternalSymbol(semanticModel.GetDeclaredSymbol(classDecl)); + + // Assert + Assert.NotNull(classSymbol); + Assert.Equal("Foo", classSymbol.Name); + Assert.Empty(semanticModel.Diagnostics); + Assert.Equal("bar", classSymbol.Members.Single().Name); + } } diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index bc8fb1c5a..cebe0d3c2 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -99,10 +99,10 @@ public static ParameterSyntax Parameter(string name, TypeSyntax type) => public static ParameterSyntax VariadicParameter(string name, TypeSyntax type) => Parameter(Ellipsis, Name(name), Colon, type); - public static SeparatedSyntaxList GenericParameterList(IEnumerable parameters) => - SeparatedSyntaxList(Comma, parameters); - public static SeparatedSyntaxList GenericParameterList(params GenericParameterSyntax[] parameters) => - SeparatedSyntaxList(Comma, parameters); + public static GenericParameterListSyntax GenericParameterList(IEnumerable parameters) => + GenericParameterList(OpenBracket, SeparatedSyntaxList(Comma, parameters), CloseBracket); + public static GenericParameterListSyntax GenericParameterList(params GenericParameterSyntax[] parameters) => + GenericParameterList(OpenBracket, SeparatedSyntaxList(Comma, parameters), CloseBracket); public static GenericParameterSyntax GenericParameter(string name) => GenericParameter(Name(name)); public static CompilationUnitSyntax CompilationUnit(IEnumerable decls) => @@ -150,7 +150,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( string name, - SeparatedSyntaxList? generics, + GenericParameterListSyntax? generics, SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration( @@ -164,14 +164,14 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( Visibility visibility, string name, - SeparatedSyntaxList? generics, + GenericParameterListSyntax? generics, SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration( VisibilityToken(visibility), Func, Name(name), - generics is null ? null : GenericParameterList(LessThan, generics, GreaterThan), + generics, OpenParen, parameters, CloseParen, @@ -309,6 +309,18 @@ public static GenericTypeSyntax GenericType( SeparatedSyntaxList(Comma, typeParameters), GreaterThan); + public static ClassDeclarationSyntax ClassDeclaration( + string name, + GenericParameterListSyntax? generics, + IEnumerable members) => ClassDeclaration( + null, + null, + Class, + Name(name), + generics, + BlockClassBody(OpenBrace, SyntaxList(members), CloseBrace) + ); + public static IndexExpressionSyntax IndexExpression(ExpressionSyntax indexed, SeparatedSyntaxList indices) => IndexExpression(indexed, OpenBracket, indices, CloseBracket); public static IndexExpressionSyntax IndexExpression(ExpressionSyntax indexed, params ExpressionSyntax[] indices) => IndexExpression(indexed, SeparatedSyntaxList(Comma, indices)); @@ -360,6 +372,7 @@ public static TextStringPartSyntax TextStringPart(string value) => public static SyntaxToken LineStringStart { get; } = MakeToken(TokenKind.LineStringStart, "\""); public static SyntaxToken LineStringEnd { get; } = MakeToken(TokenKind.LineStringEnd, "\""); public static SyntaxToken Ellipsis { get; } = MakeToken(TokenKind.Ellipsis); + public static SyntaxToken Class { get; } = MakeToken(TokenKind.KeywordClass); private static SyntaxToken MakeToken(TokenKind tokenKind) => Internal.Syntax.SyntaxToken.From(tokenKind).ToRedNode(null!, null, 0); diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index e08cdc07a..2f832fd46 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -1,5 +1,13 @@ +using System; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using Draco.Compiler.Api; +using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; +using Draco.Compiler.Internal.Declarations; namespace Draco.Compiler.Internal.Symbols.Source; @@ -10,6 +18,13 @@ internal sealed class SourceClassSymbol( Symbol containingSymbol, ClassDeclarationSyntax syntax) : TypeSymbol, ISourceSymbol { + public override ImmutableArray GenericParameters => this.BindGenericParametersIfNeeded(this.DeclaringCompilation!); + private ImmutableArray genericParameters; + + public SourceClassSymbol(Symbol containingSymbol, ClassDeclaration declaration) : this(containingSymbol, declaration.Syntax) + { + } + public override Symbol? ContainingSymbol { get; } = containingSymbol; public override string Name => this.DeclaringSyntax.Name.Text; @@ -17,15 +32,66 @@ internal sealed class SourceClassSymbol( public void Bind(IBinderProvider binderProvider) { - this.Bind + this.BindGenericParametersIfNeeded(binderProvider); + this.BindMembersIfNeeded(binderProvider); + } + + private ImmutableArray BindGenericParametersIfNeeded(IBinderProvider binderProvider) => + InterlockedUtils.InitializeDefault(ref this.genericParameters, () => this.BindGenericParameters(binderProvider)); + + private ImmutableArray BindGenericParameters(IBinderProvider binderProvider) + { + if (this.DeclaringSyntax.Generics is null) return []; + + var genericParamSyntaxes = this.DeclaringSyntax.Generics.Parameters.Values.ToList(); + var genericParams = ImmutableArray.CreateBuilder(genericParamSyntaxes.Count); + + foreach (var genericParamSyntax in genericParamSyntaxes) + { + var paramName = genericParamSyntax.Name.Text; + var usedBefore = genericParams.Any(p => p.Name == paramName); + if (usedBefore) + { + // NOTE: We only report later duplicates, no need to report the first instance + binderProvider.DiagnosticBag.Add(Diagnostic.Create( + template: SymbolResolutionErrors.IllegalShadowing, + location: genericParamSyntax.Location, + formatArgs: paramName)); + } + + var genericParam = new SourceTypeParameterSymbol(this, genericParamSyntax); + genericParams.Add(genericParam); + } + return genericParams.ToImmutable(); } + private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvider) => + InterlockedUtils.InitializeDefault(ref this.members, () => this.BindMembers(binderProvider)); + + private ImmutableArray BindMembers(IBinderProvider binder) + { + if(this.DeclaringSyntax.Body is EmptyClassBodySyntax) return []; + + var bodyClass = this.DeclaringSyntax.Body as BlockClassBodySyntax; + Debug.Assert(bodyClass is not null); + var declarationsSyntaxes = bodyClass.Declarations.ToList(); + var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count); + foreach (var declarationSyntax in declarationsSyntaxes) + { + var member = this.BindDeclaration(declarationSyntax); + members.Add(member); + } + + } - private protected string GenericsToString() + private IMemberSymbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declarationSyntax) { - if (this.IsGenericDefinition) return $"<{string.Join(", ", this.GenericParameters)}>"; - return string.Empty; + switch (declarationSyntax) + { + case FunctionDeclarationSyntax functionSyntax: + + } } - public override string ToString() => $"{this.Name}<{}>; + public override string ToString() => $"{this.Name}{this.GenericsToString()}"; } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs new file mode 100644 index 000000000..1d2a4e56f --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Draco.Compiler.Api.Syntax; + +namespace Draco.Compiler.Internal.Symbols.Source; +internal class SourceFieldSymbol : FieldSymbol, ISourceSymbol +{ + public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation); + private TypeSymbol? type; + + public override bool IsMutable => this.DeclaringSyntax.Keyword.Kind == TokenKind.KeywordVar; + + public override VariableDeclarationSyntax DeclaringSyntax { get; } +} diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs index 49d950c04..2e56faad1 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs @@ -111,7 +111,7 @@ private ImmutableArray BindGenericParameters(IBinderProvide if (this.DeclaringSyntax.Generics is null) return []; var genericParamSyntaxes = this.DeclaringSyntax.Generics.Parameters.Values.ToList(); - var genericParams = ImmutableArray.CreateBuilder(); + var genericParams = ImmutableArray.CreateBuilder(genericParamSyntaxes.Count); foreach (var genericParamSyntax in genericParamSyntaxes) { diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs index fcd91a70f..f76450e23 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs @@ -100,12 +100,14 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) FunctionDeclaration f => this.BuildFunction(f), GlobalDeclaration g => this.BuildGlobal(g), MergedModuleDeclaration m => this.BuildModule(m), + ClassDeclaration c => this.BuildClass(c), _ => throw new ArgumentOutOfRangeException(nameof(declaration)), }; private SourceFunctionSymbol BuildFunction(FunctionDeclaration declaration) => new(this, declaration); private SourceGlobalSymbol BuildGlobal(GlobalDeclaration declaration) => new(this, declaration); private SourceModuleSymbol BuildModule(MergedModuleDeclaration declaration) => new(this.DeclaringCompilation, this, declaration); + private SourceClassSymbol BuildClass(ClassDeclaration declaration) => new(this, declaration); private SymbolDocumentation BuildDocumentation() => MarkdownDocumentationExtractor.Extract(this); From 6c1f7d5117549ba308aa0fe9f8a74f3d6b5f02f5 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 15 Sep 2024 00:49:33 +0200 Subject: [PATCH 004/109] wip --- src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs | 2 + src/Draco.Compiler/Api/Syntax/TokenKind.cs | 5 ++ .../Internal/Binding/BinderFacts.cs | 1 + .../Internal/Binding/Binder_Statement.cs | 1 + .../Internal/Binding/LocalBinder.cs | 1 + .../Declarations/SingleModuleDeclaration.cs | 1 + .../Symbols/Source/SourceClassSymbol.cs | 8 +-- .../Symbols/Source/SourceFieldSymbol.cs | 25 +++++++-- .../Symbols/Source/SourcePropertySymbol.cs | 50 ++++++++++++++++++ src/Draco.Compiler/Internal/Syntax/Syntax.xml | 52 +++++++++++++++++++ 10 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs index 26ed66ea8..9bedb75ce 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Security.Principal; namespace Draco.Compiler.Api.Syntax; @@ -34,6 +35,7 @@ public static class SyntaxFacts TokenKind.KeywordNot => "not", TokenKind.KeywordOr => "or", TokenKind.KeywordPublic => "public", + TokenKind.KeywordStatic => "static", TokenKind.KeywordRem => "rem", TokenKind.KeywordReturn => "return", TokenKind.KeywordTrue => "true", diff --git a/src/Draco.Compiler/Api/Syntax/TokenKind.cs b/src/Draco.Compiler/Api/Syntax/TokenKind.cs index 0b5236ad7..99bfd1b95 100644 --- a/src/Draco.Compiler/Api/Syntax/TokenKind.cs +++ b/src/Draco.Compiler/Api/Syntax/TokenKind.cs @@ -160,6 +160,11 @@ public enum TokenKind /// KeywordPublic, + /// + /// The keyword 'static'. + /// + KeywordStatic, + /// /// The keyword 'rem'. /// diff --git a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs index e3e0e7fd0..20b5457ba 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs @@ -132,6 +132,7 @@ or WhileExpressionSyntax public static bool DefinesSymbol(SyntaxNode node) => node is FunctionDeclarationSyntax or VariableDeclarationSyntax + or FieldDeclarationSyntax or ParameterSyntax or LabelDeclarationSyntax; diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs b/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs index fe1999b13..ca79b6a76 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs @@ -33,6 +33,7 @@ internal partial class Binder InlineFunctionBodySyntax body => this.BindInlineFunctionBody(body, constraints, diagnostics), LabelDeclarationSyntax label => this.BindLabelStatement(label, constraints, diagnostics), VariableDeclarationSyntax decl => this.BindVariableDeclaration(decl, constraints, diagnostics), + FieldDeclarationSyntax field => this.BindFieldDeclaration(field, constraints, diagnostics), _ => throw new System.ArgumentOutOfRangeException(nameof(syntax)), }; diff --git a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs index 2435a7d4c..402f17c0c 100644 --- a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs @@ -173,6 +173,7 @@ private void Build() FunctionDeclarationSyntax function => new SourceFunctionSymbol(this.ContainingSymbol, function), ParameterSyntax parameter => new SourceParameterSymbol(this.ContainingSymbol, parameter), VariableDeclarationSyntax variable => new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable), + FieldDeclarationSyntax field => new SourceFieldSymbol(this.ContainingSymbol, field), LabelDeclarationSyntax label => new SourceLabelSymbol(this.ContainingSymbol, label), _ => null, }; diff --git a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs index 9131db329..2689706a8 100644 --- a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs @@ -44,6 +44,7 @@ private ImmutableArray BuildChildren() => // Since we allow for imports in local scopes too, this is the most sensible choice ImportDeclarationSyntax => null, VariableDeclarationSyntax var => new GlobalDeclaration(var), + FieldDeclarationSyntax field => new TODO(field), FunctionDeclarationSyntax func => new FunctionDeclaration(func), ClassDeclarationSyntax @class => new ClassDeclaration(@class), ModuleDeclarationSyntax module => new SingleModuleDeclaration(module.Name.Text, this.Path.Append(module.Name.Text), module), diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 2f832fd46..d922b8a36 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -70,7 +70,7 @@ private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvide private ImmutableArray BindMembers(IBinderProvider binder) { - if(this.DeclaringSyntax.Body is EmptyClassBodySyntax) return []; + if (this.DeclaringSyntax.Body is EmptyClassBodySyntax) return []; var bodyClass = this.DeclaringSyntax.Body as BlockClassBodySyntax; Debug.Assert(bodyClass is not null); @@ -78,7 +78,7 @@ private ImmutableArray BindMembers(IBinderProvider binder) var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count); foreach (var declarationSyntax in declarationsSyntaxes) { - var member = this.BindDeclaration(declarationSyntax); + var member = this.BindDeclaration(binder, declarationSyntax); members.Add(member); } @@ -88,8 +88,8 @@ private IMemberSymbol BindDeclaration(IBinderProvider binder, DeclarationSyntax { switch (declarationSyntax) { - case FunctionDeclarationSyntax functionSyntax: - + case FunctionDeclarationSyntax functionSyntax: + return new SourceFunctionSymbol(this, functionSyntax); } } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs index 1d2a4e56f..55cf9dc84 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -2,16 +2,35 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; +using Draco.Compiler.Api; using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Binding; namespace Draco.Compiler.Internal.Symbols.Source; -internal class SourceFieldSymbol : FieldSymbol, ISourceSymbol +internal class SourceFieldSymbol(FunctionSymbol containingSymbol, FieldDeclarationSyntax field) : FieldSymbol, ISourceSymbol { - public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation); + public override Symbol? ContainingSymbol => containingSymbol; + + public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation!); + + public override Api.Semantics.Visibility Visibility => this.DeclaringSyntax.Value + + private TypeSymbol BindTypeIfNeeded(Compilation declaringCompilation) => + LazyInitializer.EnsureInitialized(ref this.type, () => this.BindType(declaringCompilation)); + private TypeSymbol? type; public override bool IsMutable => this.DeclaringSyntax.Keyword.Kind == TokenKind.KeywordVar; - public override VariableDeclarationSyntax DeclaringSyntax { get; } + public override FieldDeclarationSyntax DeclaringSyntax { get; } = field; + + private TypeSymbol BindType(IBinderProvider binderProvider) + { + if (this.DeclaringSyntax.Type is null) throw new NotImplementedException(); // TODO: what should I do when the type is missing? Do we allow inference here ? + + var binder = binderProvider.GetBinder(this.DeclaringSyntax); + return binder.BindTypeToTypeSymbol(this.DeclaringSyntax.Type.Type, binderProvider.DiagnosticBag); + } } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs new file mode 100644 index 000000000..1c3689ac7 --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Draco.Compiler.Api; +using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Binding; + +namespace Draco.Compiler.Internal.Symbols.Source; +internal class SourcePropertySymbol(VariableDeclarationSyntax syntax) : PropertySymbol, ISourceSymbol, IMemberSymbol +{ + public override VariableDeclarationSyntax DeclaringSyntax { get; } = syntax; + + public override FunctionSymbol? Getter => this.BindGetterIfNeeded(this.DeclaringCompilation!); + + private FunctionSymbol? getter; + + public override FunctionSymbol? Setter => InterlockedUtils.InitializeMaybeNull(ref this.setter, this.BuildSetter); + private FunctionSymbol? setter; + + public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation!); + private TypeSymbol? type; + + + public override bool IsIndexer => throw new NotImplementedException("todo"); + + public override bool IsStatic { get; } = syntax.StaticKeyword is not null; + + private FunctionSymbol? BindGetterIfNeeded(Compilation compilation) => + InterlockedUtils.InitializeMaybeNull(ref this.getter, () => this.BindGetter(compilation)); + + private FunctionSymbol? BindGetter(Compilation compilation) + { + if (this.DeclaringSyntax.Value is null) return null; + throw new NotImplementedException("todo"); + } + + private TypeSymbol BindTypeIfNeeded(IBinderProvider binderProvider) => + LazyInitializer.EnsureInitialized(ref this.type, () => this.BindType(binderProvider)); + + private TypeSymbol BindType(IBinderProvider binderProvider) + { + if (this.DeclaringSyntax.Type is null) throw new NotImplementedException(); // TODO: what should I do when the type is missing? Do we allow inference here ? + + var binder = binderProvider.GetBinder(this.DeclaringSyntax); + return binder.BindTypeToTypeSymbol(this.DeclaringSyntax.Type.Type, binderProvider.DiagnosticBag); + } +} diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 831bf8581..70f97087d 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -534,6 +534,11 @@ + + The optional static keyword that mark this variable as static. + + + The keyword introducing the variable, either 'var' or 'val'. @@ -568,6 +573,53 @@ + + + A field declaration. + + + + + The visibility modifier keyword possibly starting the declaration. + + + + + + + + + The keyword introducing the field: 'field'. + + + + + + + The name of the declared variable. + + + + + + + The type of the declared variable. + + + + + The initializer value for the variable. + + + + + The semicolon closing the variable declaration. + + + + + + A type specifier referencing a type. From 43adfa0e161c4879551a8ed53fc117554d086ca8 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 16 Sep 2024 18:20:03 +0200 Subject: [PATCH 005/109] wip --- .../Internal/Symbols/Source/SourceFieldSymbol.cs | 3 ++- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs index 55cf9dc84..ab6ca70c4 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -15,7 +15,8 @@ internal class SourceFieldSymbol(FunctionSymbol containingSymbol, FieldDeclarati public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation!); - public override Api.Semantics.Visibility Visibility => this.DeclaringSyntax.Value + public override Api.Semantics.Visibility Visibility => + GetVisibilityFromTokenKind(this.DeclaringSyntax.VisibilityModifier); private TypeSymbol BindTypeIfNeeded(Compilation declaringCompilation) => LazyInitializer.EnsureInitialized(ref this.type, () => this.BindType(declaringCompilation)); diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index d72cfac30..59e60db85 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -35,6 +35,10 @@ + + + + From a0cab5b201f6b8cccc705d8d500170398508f547 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Tue, 17 Sep 2024 00:59:10 +0200 Subject: [PATCH 006/109] wip --- .../Internal/Binding/LocalBinder.cs | 2 +- .../Symbols/Source/SourceClassSymbol.cs | 19 +++++++++++++------ .../Symbols/Source/SourceFieldSymbol.cs | 18 ++++++++---------- .../Symbols/Source/SourcePropertySymbol.cs | 4 ++++ 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs index f23cebfdc..727dac9e4 100644 --- a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs @@ -170,7 +170,7 @@ private void Build() FunctionDeclarationSyntax function => new SourceFunctionSymbol(this.ContainingSymbol, function), ParameterSyntax parameter => new SourceParameterSymbol((FunctionSymbol)this.ContainingSymbol, parameter), VariableDeclarationSyntax variable => new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable), - FieldDeclarationSyntax field => new SourceFieldSymbol(this.ContainingSymbol, field), + FieldDeclarationSyntax field => new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, field), LabelDeclarationSyntax label => new SourceLabelSymbol(this.ContainingSymbol, label), _ => null, }; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index d922b8a36..f461e4de7 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; @@ -21,6 +22,9 @@ internal sealed class SourceClassSymbol( public override ImmutableArray GenericParameters => this.BindGenericParametersIfNeeded(this.DeclaringCompilation!); private ImmutableArray genericParameters; + public override IEnumerable DefinedMembers => this.BindMembersIfNeeded(this.DeclaringCompilation!); + private ImmutableArray definedMembers; + public SourceClassSymbol(Symbol containingSymbol, ClassDeclaration declaration) : this(containingSymbol, declaration.Syntax) { } @@ -65,31 +69,34 @@ private ImmutableArray BindGenericParameters(IBinderProvide return genericParams.ToImmutable(); } - private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvider) => - InterlockedUtils.InitializeDefault(ref this.members, () => this.BindMembers(binderProvider)); + private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvider) => + InterlockedUtils.InitializeDefault(ref this.definedMembers, () => this.BindMembers(binderProvider)); - private ImmutableArray BindMembers(IBinderProvider binder) + private ImmutableArray BindMembers(IBinderProvider binder) { if (this.DeclaringSyntax.Body is EmptyClassBodySyntax) return []; var bodyClass = this.DeclaringSyntax.Body as BlockClassBodySyntax; Debug.Assert(bodyClass is not null); var declarationsSyntaxes = bodyClass.Declarations.ToList(); - var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count); + var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count); foreach (var declarationSyntax in declarationsSyntaxes) { var member = this.BindDeclaration(binder, declarationSyntax); members.Add(member); } - + return members.ToImmutable(); } - private IMemberSymbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declarationSyntax) + private Symbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declarationSyntax) { switch (declarationSyntax) { case FunctionDeclarationSyntax functionSyntax: return new SourceFunctionSymbol(this, functionSyntax); + case FieldDeclarationSyntax fieldSyntax: + return new SourceFieldSymbol(this, fieldSyntax); + } } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs index ab6ca70c4..6804e92e3 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -1,25 +1,20 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; -using System.Threading.Tasks; -using Draco.Compiler.Api; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; namespace Draco.Compiler.Internal.Symbols.Source; -internal class SourceFieldSymbol(FunctionSymbol containingSymbol, FieldDeclarationSyntax field) : FieldSymbol, ISourceSymbol +internal class SourceFieldSymbol(TypeSymbol containingSymbol, FieldDeclarationSyntax field) : FieldSymbol, ISourceSymbol { - public override Symbol? ContainingSymbol => containingSymbol; + public override TypeSymbol ContainingSymbol => containingSymbol; public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation!); public override Api.Semantics.Visibility Visibility => - GetVisibilityFromTokenKind(this.DeclaringSyntax.VisibilityModifier); + GetVisibilityFromTokenKind(this.DeclaringSyntax.VisibilityModifier?.Kind); - private TypeSymbol BindTypeIfNeeded(Compilation declaringCompilation) => - LazyInitializer.EnsureInitialized(ref this.type, () => this.BindType(declaringCompilation)); + private TypeSymbol BindTypeIfNeeded(IBinderProvider binder) => + LazyInitializer.EnsureInitialized(ref this.type, () => this.BindType(binder)); private TypeSymbol? type; @@ -34,4 +29,7 @@ private TypeSymbol BindType(IBinderProvider binderProvider) var binder = binderProvider.GetBinder(this.DeclaringSyntax); return binder.BindTypeToTypeSymbol(this.DeclaringSyntax.Type.Type, binderProvider.DiagnosticBag); } + + public void Bind(IBinderProvider binder) => + this.BindTypeIfNeeded(binder); } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs index 1c3689ac7..7114f1cdf 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs @@ -28,6 +28,8 @@ internal class SourcePropertySymbol(VariableDeclarationSyntax syntax) : Property public override bool IsStatic { get; } = syntax.StaticKeyword is not null; + public override bool IsExplicitImplementation => throw new NotImplementedException(); + private FunctionSymbol? BindGetterIfNeeded(Compilation compilation) => InterlockedUtils.InitializeMaybeNull(ref this.getter, () => this.BindGetter(compilation)); @@ -47,4 +49,6 @@ private TypeSymbol BindType(IBinderProvider binderProvider) var binder = binderProvider.GetBinder(this.DeclaringSyntax); return binder.BindTypeToTypeSymbol(this.DeclaringSyntax.Type.Type, binderProvider.DiagnosticBag); } + + public void Bind(IBinderProvider binderProvider) => throw new NotImplementedException(); } From 616ad1814d393c7933b68d24222d44bad38d90eb Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 18 Sep 2024 01:25:31 +0200 Subject: [PATCH 007/109] yes there is no message commit because it will get squashed --- .../Semantics/SemanticModelTests.cs | 2 +- .../Api/Syntax/SyntaxFactory.cs | 48 +++++++---------- .../Internal/Binding/Binder_Statement.cs | 1 - .../Declarations/SingleModuleDeclaration.cs | 2 +- .../Symbols/Source/SourceClassSymbol.cs | 3 +- .../Symbols/Source/SourcePropertySymbol.cs | 54 ------------------- src/Draco.Compiler/Internal/Syntax/Parser.cs | 33 ++++++------ src/Draco.Compiler/Internal/Syntax/Syntax.xml | 8 +-- 8 files changed, 43 insertions(+), 108 deletions(-) delete mode 100644 src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs diff --git a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs index 8ef0ce3da..f9d446f84 100644 --- a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs @@ -494,7 +494,7 @@ public void GetReferencedSymbolFromSourceClassSymbol() [FunctionDeclaration("bar", ParameterList(), null, BlockFunctionBody())] ))); var compilation = CreateCompilation(tree); - var classDecl = tree.FindInChildren(0); + var classDecl = tree.GetNode(0); Assert.NotNull(classDecl); // Act diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index 2a966ca5b..1c1b5f0fe 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -103,15 +103,9 @@ public static ParameterSyntax VariadicParameter(string name, TypeSyntax type) => Parameter(SyntaxList(), Ellipsis, Identifier(name), Colon, type); public static GenericParameterListSyntax GenericParameterList(IEnumerable parameters) => - GenericParameterList(OpenBracket, SeparatedSyntaxList(Comma, parameters), CloseBracket); + GenericParameterList(SeparatedSyntaxList(Comma, parameters)); public static GenericParameterListSyntax GenericParameterList(params GenericParameterSyntax[] parameters) => - GenericParameterList(OpenBracket, SeparatedSyntaxList(Comma, parameters), CloseBracket); - public static GenericParameterSyntax GenericParameter(string name) => GenericParameter(Name(name)); - - public static CompilationUnitSyntax CompilationUnit(IEnumerable decls) => - CompilationUnit(SyntaxList(decls), EndOfInput); - public static CompilationUnitSyntax CompilationUnit(params DeclarationSyntax[] decls) => - CompilationUnit(SyntaxList(decls), EndOfInput); + GenericParameterList(SeparatedSyntaxList(Comma, parameters)); public static ModuleDeclarationSyntax ModuleDeclaration(string name, IEnumerable declarations) => ModuleDeclaration([], null, name, declarations); @@ -164,47 +158,45 @@ public static FunctionDeclarationSyntax FunctionDeclaration( SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration( - attributes, - Visibility(visibility), - Func, - Name(name), - generics, - OpenParen, - parameters, - CloseParen, - returnType is null ? null : TypeSpecifier(Colon, returnType), - body); + attributes, + Visibility(visibility), + name, + generics, + parameters, + returnType is null ? null : TypeSpecifier(returnType), + body); public static VariableDeclarationSyntax VariableDeclaration( string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(null, true, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration(null, null, true, name, type, value); public static VariableDeclarationSyntax VariableDeclaration( Visibility visibility, string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), true, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), null, true, name, type, value); public static VariableDeclarationSyntax ImmutableVariableDeclaration( string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(null, false, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration(null, null, false, name, type, value); public static VariableDeclarationSyntax ImmutableVariableDeclaration( Visibility visibility, string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), false, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), null, false, name, type, value); public static VariableDeclarationSyntax VariableDeclaration( TokenKind? visibility, + TokenKind? global, bool isMutable, string name, - TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration( + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration( [], visibility, + global, isMutable ? TokenKind.KeywordVar : TokenKind.KeywordVal, name, type is null ? null : TypeSpecifier(type), @@ -259,12 +251,10 @@ public static ClassDeclarationSyntax ClassDeclaration( IEnumerable members) => ClassDeclaration( null, null, - Class, - Name(name), + name, generics, - BlockClassBody(OpenBrace, SyntaxList(members), CloseBrace) + BlockClassBody(members) ); - public static IndexExpressionSyntax IndexExpression(ExpressionSyntax indexed, params ExpressionSyntax[] indices) => IndexExpression(indexed, SeparatedSyntaxList(Comma, indices)); @@ -273,7 +263,7 @@ public static IndexExpressionSyntax IndexExpression(ExpressionSyntax indexed, pa public static LiteralExpressionSyntax LiteralExpression(int value) => LiteralExpression(Integer(value)); public static LiteralExpressionSyntax LiteralExpression(bool value) => LiteralExpression(value ? KeywordTrue : KeywordFalse); public static StringExpressionSyntax StringExpression(string value) => - StringExpression(LineStringStart, [TextStringPart(value)], LineStringEnd); + StringExpression(LineStringStart, SyntaxList(TextStringPart(value)), LineStringEnd); public static TextStringPartSyntax TextStringPart(string value) => TextStringPart(Token(TokenKind.StringContent, value, value)); diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs b/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs index ca79b6a76..fe1999b13 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Statement.cs @@ -33,7 +33,6 @@ internal partial class Binder InlineFunctionBodySyntax body => this.BindInlineFunctionBody(body, constraints, diagnostics), LabelDeclarationSyntax label => this.BindLabelStatement(label, constraints, diagnostics), VariableDeclarationSyntax decl => this.BindVariableDeclaration(decl, constraints, diagnostics), - FieldDeclarationSyntax field => this.BindFieldDeclaration(field, constraints, diagnostics), _ => throw new System.ArgumentOutOfRangeException(nameof(syntax)), }; diff --git a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs index 2689706a8..27f777750 100644 --- a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Linq; using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Symbols.Source; namespace Draco.Compiler.Internal.Declarations; @@ -44,7 +45,6 @@ private ImmutableArray BuildChildren() => // Since we allow for imports in local scopes too, this is the most sensible choice ImportDeclarationSyntax => null, VariableDeclarationSyntax var => new GlobalDeclaration(var), - FieldDeclarationSyntax field => new TODO(field), FunctionDeclarationSyntax func => new FunctionDeclaration(func), ClassDeclarationSyntax @class => new ClassDeclaration(@class), ModuleDeclarationSyntax module => new SingleModuleDeclaration(module.Name.Text, this.Path.Append(module.Name.Text), module), diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index f461e4de7..ac141bc12 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -96,7 +96,8 @@ private Symbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declara return new SourceFunctionSymbol(this, functionSyntax); case FieldDeclarationSyntax fieldSyntax: return new SourceFieldSymbol(this, fieldSyntax); - + default: + throw new NotImplementedException(); // TODO implement this } } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs deleted file mode 100644 index 7114f1cdf..000000000 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourcePropertySymbol.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Draco.Compiler.Api; -using Draco.Compiler.Api.Syntax; -using Draco.Compiler.Internal.Binding; - -namespace Draco.Compiler.Internal.Symbols.Source; -internal class SourcePropertySymbol(VariableDeclarationSyntax syntax) : PropertySymbol, ISourceSymbol, IMemberSymbol -{ - public override VariableDeclarationSyntax DeclaringSyntax { get; } = syntax; - - public override FunctionSymbol? Getter => this.BindGetterIfNeeded(this.DeclaringCompilation!); - - private FunctionSymbol? getter; - - public override FunctionSymbol? Setter => InterlockedUtils.InitializeMaybeNull(ref this.setter, this.BuildSetter); - private FunctionSymbol? setter; - - public override TypeSymbol Type => this.BindTypeIfNeeded(this.DeclaringCompilation!); - private TypeSymbol? type; - - - public override bool IsIndexer => throw new NotImplementedException("todo"); - - public override bool IsStatic { get; } = syntax.StaticKeyword is not null; - - public override bool IsExplicitImplementation => throw new NotImplementedException(); - - private FunctionSymbol? BindGetterIfNeeded(Compilation compilation) => - InterlockedUtils.InitializeMaybeNull(ref this.getter, () => this.BindGetter(compilation)); - - private FunctionSymbol? BindGetter(Compilation compilation) - { - if (this.DeclaringSyntax.Value is null) return null; - throw new NotImplementedException("todo"); - } - - private TypeSymbol BindTypeIfNeeded(IBinderProvider binderProvider) => - LazyInitializer.EnsureInitialized(ref this.type, () => this.BindType(binderProvider)); - - private TypeSymbol BindType(IBinderProvider binderProvider) - { - if (this.DeclaringSyntax.Type is null) throw new NotImplementedException(); // TODO: what should I do when the type is missing? Do we allow inference here ? - - var binder = binderProvider.GetBinder(this.DeclaringSyntax); - return binder.BindTypeToTypeSymbol(this.DeclaringSyntax.Type.Type, binderProvider.DiagnosticBag); - } - - public void Bind(IBinderProvider binderProvider) => throw new NotImplementedException(); -} diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 72daaf1bc..628a87311 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -361,6 +361,7 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) { var attributes = this.ParseAttributeList(); var visibility = this.ParseVisibilityModifier(); + var global = this.ParseGlobalModifier(); // todo: check for global on other constructions and show custom error. switch (this.PeekKind()) { case TokenKind.KeywordImport: @@ -369,11 +370,10 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordValue: { var valueKeyword = this.Expect(TokenKind.KeywordValue); - return this.ParseClassDeclaration(visibility: visibility, valueType: valueKeyword); + return this.ParseClassDeclaration(visibility: visibility, global: global, valueType: valueKeyword); } - case TokenKind.KeywordClass: - return this.ParseClassDeclaration(visibility: visibility, valueType: null); + return this.ParseClassDeclaration(visibility: visibility, global: global, valueType: null); case TokenKind.KeywordFunc: return this.ParseFunctionDeclaration(attributes, visibility, context); @@ -383,7 +383,7 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordVar: case TokenKind.KeywordVal: - return this.ParseVariableDeclaration(attributes, visibility, context); + return this.ParseVariableDeclaration(attributes, visibility, global, context); case TokenKind.Identifier when this.PeekKind(1) == TokenKind.Colon: return this.ParseLabelDeclaration(attributes, visibility, context); @@ -529,7 +529,7 @@ private ImportPathSyntax ParseImportPath() /// Optional visibility modifier token. /// Optional valuetype modifier token. /// The parsed . - private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, SyntaxToken? valueType) + private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, SyntaxToken? global, SyntaxToken? valueType) { // Class keyword and name of the class var classKeyword = this.Expect(TokenKind.KeywordClass); @@ -537,7 +537,7 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, Sy // Optional generics var generics = null as GenericParameterListSyntax; - if (this.Peek() == TokenKind.LessThan) generics = this.ParseGenericParameterList(); + if (this.PeekKind() == TokenKind.LessThan) generics = this.ParseGenericParameterList(); var body = this.ParseClassBody(); @@ -556,16 +556,12 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, Sy /// The parsed . private ClassBodySyntax ParseClassBody() { - switch (this.Peek()) + return this.PeekKind() switch { - case TokenKind.Semicolon: - return this.ParseEmptyClassBody(); - case TokenKind.CurlyOpen: - return this.ParseBlockClassBody(); - default: - // TODO - throw new NotImplementedException(); - } + TokenKind.Semicolon => this.ParseEmptyClassBody(), + TokenKind.CurlyOpen => this.ParseBlockClassBody(), + _ => throw new NotImplementedException(),// TODO + }; } /// @@ -589,7 +585,7 @@ private BlockClassBodySyntax ParseBlockClassBody() while (true) { // Break on the end of the block - if (this.Peek() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; + if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; // Parse a declaration var decl = this.ParseDeclaration(DeclarationContext.Global); @@ -609,6 +605,7 @@ private BlockClassBodySyntax ParseBlockClassBody() private VariableDeclarationSyntax ParseVariableDeclaration( SyntaxList? attributes, SyntaxToken? visibility, + SyntaxToken? global, DeclarationContext context) { if (context == DeclarationContext.Local && attributes is not null) @@ -638,7 +635,7 @@ private VariableDeclarationSyntax ParseVariableDeclaration( } // Eat semicolon at the end of declaration var semicolon = this.Expect(TokenKind.Semicolon); - return new VariableDeclarationSyntax(attributes, visibility, keyword, identifier, type, assignment, semicolon); + return new VariableDeclarationSyntax(attributes, visibility, global, keyword, identifier, type, assignment, semicolon); } /// @@ -1601,6 +1598,8 @@ private SeparatedSyntaxList ParseSeparatedSyntaxList( private SyntaxToken? ParseVisibilityModifier() => IsVisibilityModifier(this.PeekKind()) ? this.Advance() : null; + private SyntaxToken? ParseGlobalModifier() => this.PeekKind() == TokenKind.KeywordGlobal ? this.Advance() : null; + private bool CanBailOut(SyntaxNode node) { if (parserMode != ParserMode.Repl) return false; diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 59e60db85..ce4cd09f2 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -35,7 +35,7 @@ - + @@ -666,9 +666,9 @@ - - The optional static keyword that mark this variable as static. - + + The optional global keyword that mark this variable as global. + From 8b6c18475d91dfa43ef8fa5064541ceb7381bd90 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 19 Sep 2024 00:18:55 +0200 Subject: [PATCH 008/109] progress. --- .../Internal/Binding/BinderCache.cs | 16 ++++++- .../Internal/Binding/BinderFacts.cs | 6 ++- .../Internal/Binding/ClassBinder.cs | 45 +++++++++++++++++++ 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Binding/ClassBinder.cs diff --git a/src/Draco.Compiler/Internal/Binding/BinderCache.cs b/src/Draco.Compiler/Internal/Binding/BinderCache.cs index fab218681..5f7d5667e 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderCache.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderCache.cs @@ -36,7 +36,8 @@ public Binder GetBinder(SyntaxNode syntax) CompilationUnitSyntax cu => this.BuildCompilationUnitBinder(cu), ScriptEntrySyntax entry => this.BuildScriptEntryBinder(entry), ModuleDeclarationSyntax mo => this.BuildModuleBinder(mo), - FunctionDeclarationSyntax decl => this.BuildFunctionDeclarationBinder(decl), + FunctionDeclarationSyntax funcDecl => this.BuildFunctionDeclarationBinder(funcDecl), + ClassDeclarationSyntax classDecl => this.BuildClassDeclarationBinder(classDecl), FunctionBodySyntax body => this.BuildFunctionBodyBinder(body), BlockExpressionSyntax block => this.BuildLocalBinder(block), WhileExpressionSyntax loop => this.BuildLoopBinder(loop), @@ -94,6 +95,19 @@ private FunctionBinder BuildFunctionDeclarationBinder(FunctionDeclarationSyntax return new FunctionBinder(binder, functionSymbol); } + private ClassBinder BuildClassDeclarationBinder(ClassDeclarationSyntax syntax) + { + Debug.Assert(syntax.Parent is not null); + var binder = this.GetBinder(syntax.Parent); + + var parent = UnwrapFromImportBinder(binder); + var classSymbol = parent.DeclaredSymbols + .OfType() + .FirstOrDefault(member => member.DeclaringSyntax == syntax); // should we shove that in an helper ? + return new ClassBinder(parent, classSymbol); + } + + private Binder BuildFunctionBodyBinder(FunctionBodySyntax syntax) { Debug.Assert(syntax.Parent is not null); diff --git a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs index cc248c8f2..aac00d076 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs @@ -123,7 +123,8 @@ or ModuleDeclarationSyntax or FunctionBodySyntax or BlockExpressionSyntax or WhileExpressionSyntax - or ForExpressionSyntax; + or ForExpressionSyntax + or ClassDeclarationSyntax; /// /// Checks, if a given syntax node defines a symbol. @@ -135,7 +136,8 @@ is FunctionDeclarationSyntax or VariableDeclarationSyntax or FieldDeclarationSyntax or ParameterSyntax - or LabelDeclarationSyntax; + or LabelDeclarationSyntax + or ClassDeclarationSyntax; /// /// Checks, if a given syntax node references a symbol. diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs new file mode 100644 index 000000000..7b4cf9f7b --- /dev/null +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Symbols; +using Draco.Compiler.Internal.Symbols.Source; + +namespace Draco.Compiler.Internal.Binding; +internal sealed class ClassBinder(Binder parent, TypeSymbol symbol) : Binder(parent) +{ + public override Symbol? ContainingSymbol => this.symbol; + public override SyntaxNode? DeclaringSyntax => this.symbol.DeclaringSyntax; + + private readonly Symbol symbol = symbol; + + public override IEnumerable DeclaredSymbols => this.symbol.Members + .Cast() + .Concat(this.symbol.GenericParameters); + + internal override void LookupLocal(LookupResult result, string name, ref LookupFlags flags, Predicate allowSymbol, SyntaxNode? currentReference) + { + // copied from the function binder, as far as i understand it, it should be the same. + foreach (var typeParam in this.symbol.GenericParameters) + { + if (typeParam.Name != name) continue; + if (!allowSymbol(typeParam)) continue; + result.Add(typeParam); + break; + } + + if (flags.HasFlag(LookupFlags.DisallowLocals)) return; + + foreach (var member in this.symbol.Members) + { + if (member.Name != name) continue; + if (!allowSymbol(member)) continue; + result.Add(member); + break; + } + + flags |= LookupFlags.DisallowLocals | LookupFlags.AllowGlobals; + } +} From c1b941e6b08405e9d2aee0a22a3f5415f7add4f5 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 19 Sep 2024 11:04:10 +0200 Subject: [PATCH 009/109] binding & symbols works. --- src/Draco.Compiler/Api/Semantics/SemanticModel.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Draco.Compiler/Api/Semantics/SemanticModel.cs b/src/Draco.Compiler/Api/Semantics/SemanticModel.cs index 0e83b2233..67ac33c01 100644 --- a/src/Draco.Compiler/Api/Semantics/SemanticModel.cs +++ b/src/Draco.Compiler/Api/Semantics/SemanticModel.cs @@ -186,6 +186,15 @@ public ImmutableArray GetAllAccessibleSymbols(SyntaxNode? node) .SingleOrDefault(sym => sym.DeclaringSyntax == syntax); return symbol; } + case SourceClassSymbol classSymbol: + { + if (classSymbol.DeclaringSyntax == syntax) return containingSymbol; + + var symbol = classSymbol.Members + .SingleOrDefault(sym => sym.DeclaringSyntax == syntax); + + return symbol; + } default: return null; } From 242d9b83018fbebf047803c5ab5ef3dd3e28caf4 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 23 Sep 2024 03:02:11 +0200 Subject: [PATCH 010/109] wip --- .../Internal/OptimizingIr/Model/Field.cs | 17 ++++++++ .../Internal/OptimizingIr/Model/IField.cs | 32 ++++++++++++++ .../Internal/OptimizingIr/Model/IModule.cs | 6 +++ .../Internal/OptimizingIr/Model/IProcedure.cs | 6 +++ .../Internal/OptimizingIr/Model/IType.cs | 37 ++++++++++++++++ .../Internal/OptimizingIr/Model/Module.cs | 6 ++- .../Internal/OptimizingIr/Model/Procedure.cs | 7 +++- .../Internal/OptimizingIr/Model/Type.cs | 42 +++++++++++++++++++ .../Internal/Symbols/AttributeInstance.cs | 2 +- .../Internal/Symbols/SymbolVisitor.cs | 1 + .../Internal/Symbols/WellKnownTypes.cs | 4 +- 11 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs create mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs create mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs create mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs new file mode 100644 index 000000000..8e47b1c1d --- /dev/null +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Draco.Compiler.Internal.Symbols; + +namespace Draco.Compiler.Internal.OptimizingIr.Model; +internal class Field(FieldSymbol symbol, Type declaringType) : IField +{ + public FieldSymbol Symbol { get; } = symbol; + + public string Name => this.Symbol.Name; + + public Type DeclaringType { get; } = declaringType; + IType IField.DeclaringType => this.DeclaringType; + + public IReadOnlyList Attributes => this.Symbol.Attributes; + + public TypeSymbol Type => this.Symbol.Type; +} diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs new file mode 100644 index 000000000..a818dfb2b --- /dev/null +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using Draco.Compiler.Internal.Symbols; + +namespace Draco.Compiler.Internal.OptimizingIr.Model; + +/// +/// Read-only interface of a field. +/// +internal interface IField +{ + public FieldSymbol Symbol { get; } + + /// + /// The name of this field. + /// + public string Name { get; } + + /// + /// The type this procedure is defined in. + /// + public IType DeclaringType { get; } + + /// + /// The attributes on this field. + /// + public IReadOnlyList Attributes { get; } + + /// + /// The type of this field. + /// + public TypeSymbol Type { get; } +} diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs index fe07e6f71..2b370f737 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Draco.Compiler.Internal.Symbols; +using Draco.Compiler.Internal.Symbols.Source; namespace Draco.Compiler.Internal.OptimizingIr.Model; @@ -43,6 +44,11 @@ internal interface IModule /// public IReadOnlyDictionary Procedures { get; } + /// + /// The compiled types within this module. + /// + public IReadOnlyDictionary Types { get; } + /// /// The procedure performing global initialization. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs index 1b94b1692..2740da8af 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs @@ -18,6 +18,12 @@ internal interface IProcedure /// public string Name { get; } + /// + /// The type this procedure is defined in. + /// When , this procedure is a free function. + /// + public IType? DeclaringType { get; } + /// /// The module this procedure is defined in. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs new file mode 100644 index 000000000..82a57ea5f --- /dev/null +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using Draco.Compiler.Internal.Symbols; + +namespace Draco.Compiler.Internal.OptimizingIr.Model; + +internal interface IType +{ + /// + /// The name of this type. + /// + public string Name { get; } + + /// + /// The module this type is defined in. + /// + public IModule DeclaringModule { get; } + + /// + /// The assembly this type is defined in. + /// + public IAssembly Assembly { get; } + + /// + /// The generic parameters on this type. + /// + public IReadOnlyList Generics { get; } + + /// + /// The methods on this type. + /// + public IReadOnlyDictionary Methods { get; } + + /// + /// The fields on this type. + /// + public IReadOnlyDictionary Fields { get; } +} diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index 29aa3e6cb..ec5fc2861 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -18,6 +18,9 @@ internal sealed class Module : IModule public IDictionary Submodules => this.submodules; IReadOnlyDictionary IModule.Submodules => this.submodules; + public IDictionary Types => this.types; + IReadOnlyDictionary IModule.Types => this.types; + public IReadOnlySet Globals => this.globals; public Procedure GlobalInitializer { get; } @@ -35,6 +38,7 @@ internal sealed class Module : IModule private readonly HashSet globals = []; private readonly Dictionary procedures = []; private readonly Dictionary submodules = []; + private readonly Dictionary types = []; public Module(ModuleSymbol symbol, Assembly assembly, Module? Parent) { @@ -64,7 +68,7 @@ public Procedure DefineProcedure(FunctionSymbol functionSymbol) { if (!this.procedures.TryGetValue(functionSymbol, out var result)) { - result = new Procedure(this, functionSymbol); + result = new Procedure(this, null, functionSymbol); this.procedures.Add(functionSymbol, result); } return (Procedure)result; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index 39a4d2b2d..0ce3ecc8f 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -13,9 +13,11 @@ internal sealed class Procedure : IProcedure { public FunctionSymbol Symbol { get; } public string Name => this.Symbol.NestedName; - public TypeSymbol? Type => this.Symbol.Type; + public TypeSymbol? TypeSymbol => this.Symbol.Type; public Module DeclaringModule { get; } IModule IProcedure.DeclaringModule => this.DeclaringModule; + public Type? DeclaringType { get; } + IType? IProcedure.DeclaringType => this.DeclaringType; public Assembly Assembly => this.DeclaringModule.Assembly; IAssembly IProcedure.Assembly => this.Assembly; public BasicBlock Entry { get; } @@ -35,9 +37,10 @@ internal sealed class Procedure : IProcedure private readonly List locals = []; private readonly List registers = []; - public Procedure(Module declaringModule, FunctionSymbol symbol) + public Procedure(Module declaringModule, Type? declaringType, FunctionSymbol symbol) { this.DeclaringModule = declaringModule; + this.DeclaringType = declaringType; this.Symbol = symbol; this.Entry = this.DefineBasicBlock(new SynthetizedLabelSymbol("begin")); } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs new file mode 100644 index 000000000..1391dd68a --- /dev/null +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using Draco.Compiler.Internal.Symbols; + +namespace Draco.Compiler.Internal.OptimizingIr.Model; +internal class Type(Module declaringModule, TypeSymbol symbol) : IType +{ + + public TypeSymbol Symbol { get; } = symbol; + public string Name => this.Symbol.Name; + + public Module DeclaringModule { get; } = declaringModule; + IModule IType.DeclaringModule => this.DeclaringModule; + public Assembly Assembly => this.DeclaringModule.Assembly; + IAssembly IType.Assembly => this.Assembly; + + public IReadOnlyList Generics => this.Symbol.GenericParameters; + public IReadOnlyDictionary Methods => this.methods; + public IReadOnlyDictionary Fields => this.fields; + + private readonly Dictionary methods = []; + private readonly Dictionary fields = []; + + public Procedure DefineMethod(FunctionSymbol functionSymbol) + { + if (!this.methods.TryGetValue(functionSymbol, out var result)) + { + result = new Procedure(this.DeclaringModule, this, functionSymbol); + this.methods.Add(functionSymbol, result); + } + return (Procedure)result; + } + + public Field DefineField(FieldSymbol fieldSymbol) + { + if (!this.fields.TryGetValue(fieldSymbol, out var result)) + { + result = new Field(fieldSymbol, this); + this.fields.Add(fieldSymbol, result); + } + return (Field)result; + } +} diff --git a/src/Draco.Compiler/Internal/Symbols/AttributeInstance.cs b/src/Draco.Compiler/Internal/Symbols/AttributeInstance.cs index 954db4ef8..4c6b5227f 100644 --- a/src/Draco.Compiler/Internal/Symbols/AttributeInstance.cs +++ b/src/Draco.Compiler/Internal/Symbols/AttributeInstance.cs @@ -106,7 +106,7 @@ private bool TypesMatch(System.Type reflType, TypeSymbol internalType) var wellKnownTypes = this.Constructor.DeclaringCompilation?.WellKnownTypes; if (wellKnownTypes is null) throw new System.NotImplementedException(); - var translatedReflType = wellKnownTypes.TranslatePrmitive(reflType); + var translatedReflType = wellKnownTypes.TranslatePrimitive(reflType); if (translatedReflType is null) throw new System.NotImplementedException(); return SymbolEqualityComparer.Default.Equals(translatedReflType, internalType); diff --git a/src/Draco.Compiler/Internal/Symbols/SymbolVisitor.cs b/src/Draco.Compiler/Internal/Symbols/SymbolVisitor.cs index c15b3bb2c..2000a413d 100644 --- a/src/Draco.Compiler/Internal/Symbols/SymbolVisitor.cs +++ b/src/Draco.Compiler/Internal/Symbols/SymbolVisitor.cs @@ -15,6 +15,7 @@ public virtual void VisitFunction(FunctionSymbol functionSymbol) public virtual void VisitType(TypeSymbol typeSymbol) { + foreach (var genericParam in typeSymbol.GenericParameters) genericParam.Accept(this); foreach (var member in typeSymbol.Members) member.Accept(this); } diff --git a/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs b/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs index dd408978c..0a81bb505 100644 --- a/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs +++ b/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs @@ -203,7 +203,7 @@ public IEnumerable GetEnumEqualityMembers(TypeSymbol type) /// /// The reflected type to translate. /// The translated type symbol, or if it's not a translatable primitive type. - public TypeSymbol? TranslatePrmitive(Type type) + public TypeSymbol? TranslatePrimitive(System.Type type) { if (type == typeof(byte)) return this.SystemByte; if (type == typeof(ushort)) return this.SystemUInt16; @@ -224,7 +224,7 @@ public IEnumerable GetEnumEqualityMembers(TypeSymbol type) if (type == typeof(string)) return this.SystemString; if (type == typeof(object)) return this.SystemObject; - if (type == typeof(Type)) return this.SystemType; + if (type == typeof(System.Type)) return this.SystemType; return null; } From 991e13d6245e99e4a2ea986de91bc48d2e30cf05 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 29 Sep 2024 00:14:56 +0200 Subject: [PATCH 011/109] wip --- .../EndToEnd/CodeExecutionTests.cs | 35 ++++++++ .../Internal/Binding/BinderCache.cs | 4 + .../Internal/Codegen/MetadataCodegen.cs | 89 +++++++++++++++++++ .../Internal/OptimizingIr/Model/IType.cs | 5 ++ src/Draco.Compiler/Internal/Syntax/Lexer.cs | 1 + 5 files changed, 134 insertions(+) create mode 100644 src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs new file mode 100644 index 000000000..2d0512a21 --- /dev/null +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static Draco.Compiler.Tests.TestUtilities; + +namespace Draco.Compiler.Tests.EndToEnd; + +[Collection(nameof(NoParallelizationCollectionDefinition))] +public class CodeExecutionTests +{ + [Fact] + public void ClassHelloWorld() + { + var assembly = CompileToAssembly(""" + import System.Console; + + func main() { + WriteLine("Hello, World!"); + } + + class Foo { + global func bar() { + WriteLine("Hello, World!"); + } + } + """); + + var stringWriter = new StringWriter(); + _ = Invoke(assembly: assembly, stdout: stringWriter); + + Assert.Equal($"Hello, World!{Environment.NewLine}", stringWriter.ToString(), ignoreLineEndingDifferences: true); + } +} diff --git a/src/Draco.Compiler/Internal/Binding/BinderCache.cs b/src/Draco.Compiler/Internal/Binding/BinderCache.cs index 5f7d5667e..c62da3d9a 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderCache.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderCache.cs @@ -25,6 +25,10 @@ internal sealed class BinderCache(Compilation compilation) /// The binder for . public Binder GetBinder(SyntaxNode syntax) { + if(syntax is ClassDeclarationSyntax ) + { + + } var scopeDefiningAncestor = BinderFacts.GetScopeDefiningAncestor(syntax); Debug.Assert(scopeDefiningAncestor is not null); diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index ec5cab25a..93b23103d 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -98,6 +98,7 @@ public static void Generate( private readonly Dictionary intrinsicReferenceHandles = []; private readonly AssemblyReferenceHandle systemRuntimeReference; private readonly TypeReferenceHandle systemObjectReference; + private readonly TypeReferenceHandle systemValueTypeReference; private MetadataCodegen(Compilation compilation, IAssembly assembly, CodegenFlags flags) { @@ -120,6 +121,11 @@ private MetadataCodegen(Compilation compilation, IAssembly assembly, CodegenFlag assembly: this.systemRuntimeReference, @namespace: "System", name: "Object"); + + this.systemValueTypeReference = this.GetOrAddTypeReference( + assembly: this.systemRuntimeReference, + @namespace: "System", + name: "ValueType"); } private void WriteModuleAndAssemblyDefinition() @@ -648,6 +654,89 @@ private BlobHandle EncodeAttributeSignature(AttributeInstance attribute) }); } + private TypeDefinitionHandle EncodeClass( + IType type, + TypeDefinitionHandle? parent, + ref int fieldIndex, + ref int procIndex + ) + { + var startFieldIndex = fieldIndex; + var startProcIndex = procIndex; + + var visibility = (type.Symbol.Visibility, parent) switch + { + (Api.Semantics.Visibility.Public, not null) => TypeAttributes.NestedPublic, + (Api.Semantics.Visibility.Public, null) => TypeAttributes.Public, + (_, not null) => TypeAttributes.NestedAssembly, + (_, null) => TypeAttributes.NotPublic, + }; + + var attributes = visibility | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed; + + if (type.Symbol.IsValueType) attributes |= TypeAttributes.SequentialLayout; // AutoLayout = 0. + + var createdClass = this.AddTypeDefinition( + attributes, + null, + type.Name, + type.Symbol.IsValueType ? this.systemValueTypeReference : this.systemObjectReference, + fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), + methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex) + ); + + // Procedures + foreach (var proc in type.Methods.Values) + { + var handle = this.EncodeProcedure(proc); + ++procIndex; + + // Todo: properties + } + + // Fields + foreach (var field in type.Fields) + { + this.EncodeField(field.Key); + ++fieldIndex; + } + + // If this is a valuetype without fields, we add .pack 0 and .size 1 + if (type.Symbol.IsValueType && type.Fields.Count == 0) + { + this.MetadataBuilder.AddTypeLayout( + type: createdClass, + packingSize: 0, + size: 1); + } + + // If this isn't top level module, we specify nested relationship + if (parent is not null) this.MetadataBuilder.AddNestedType(createdClass, parent.Value); + + return createdClass; + } + + private FieldDefinitionHandle EncodeField(FieldSymbol field) + { + var visibility = field.Visibility switch + { + Api.Semantics.Visibility.Public => FieldAttributes.Public, + Api.Semantics.Visibility.Internal => FieldAttributes.Assembly, + Api.Semantics.Visibility.Private => FieldAttributes.Private, + _ => throw new IndexOutOfRangeException(nameof(field.Visibility)), + }; + var mutability = field.IsMutable ? default : FieldAttributes.InitOnly; + + // Definition + return this.AddFieldDefinition( + attributes: visibility | mutability, + name: field.Name, + signature: this.EncodeFieldSignature(field)); + } + + private BlobHandle EncodeFieldSignature(FieldSymbol field) => + this.EncodeBlob(e => this.EncodeSignatureType(e.Field().Type(), field.Type)); + private IEnumerable ScalarConstantTypes => [ this.WellKnownTypes.SystemSByte, this.WellKnownTypes.SystemInt16, diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs index 82a57ea5f..b51770cd8 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs @@ -5,6 +5,11 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; internal interface IType { + /// + /// The symbol of this type. + /// + public TypeSymbol Symbol { get; } + /// /// The name of this type. /// diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 63ffa00fe..96b598c17 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -331,6 +331,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) { "and" => TokenKind.KeywordAnd, "class" => TokenKind.KeywordClass, + "global" => TokenKind.KeywordGlobal, "else" => TokenKind.KeywordElse, "false" => TokenKind.KeywordFalse, "for" => TokenKind.KeywordFor, From 73e6a15a09b5782342e213987d0674f7dddab82d Mon Sep 17 00:00:00 2001 From: Kuinox Date: Tue, 1 Oct 2024 01:27:18 +0200 Subject: [PATCH 012/109] fix --- src/Draco.Compiler/Internal/Binding/BinderCache.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Binding/BinderCache.cs b/src/Draco.Compiler/Internal/Binding/BinderCache.cs index c62da3d9a..8bad324b2 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderCache.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderCache.cs @@ -108,7 +108,7 @@ private ClassBinder BuildClassDeclarationBinder(ClassDeclarationSyntax syntax) var classSymbol = parent.DeclaredSymbols .OfType() .FirstOrDefault(member => member.DeclaringSyntax == syntax); // should we shove that in an helper ? - return new ClassBinder(parent, classSymbol); + return new ClassBinder(binder, classSymbol); } From 231feb25213c219677232b69e0c759af44cca805 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 3 Oct 2024 00:55:24 +0200 Subject: [PATCH 013/109] wip --- .../Internal/Binding/BinderCache.cs | 4 ---- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 2 +- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 22 ++++++++++++++++++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/BinderCache.cs b/src/Draco.Compiler/Internal/Binding/BinderCache.cs index 8bad324b2..b773fbe9c 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderCache.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderCache.cs @@ -25,10 +25,6 @@ internal sealed class BinderCache(Compilation compilation) /// The binder for . public Binder GetBinder(SyntaxNode syntax) { - if(syntax is ClassDeclarationSyntax ) - { - - } var scopeDefiningAncestor = BinderFacts.GetScopeDefiningAncestor(syntax); Debug.Assert(scopeDefiningAncestor is not null); diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 96b598c17..afd48f15a 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -331,7 +331,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) { "and" => TokenKind.KeywordAnd, "class" => TokenKind.KeywordClass, - "global" => TokenKind.KeywordGlobal, + "this" => TokenKind.KeywordThis, "else" => TokenKind.KeywordElse, "false" => TokenKind.KeywordFalse, "for" => TokenKind.KeywordFor, diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index ce4cd09f2..5196b59b0 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -36,6 +36,7 @@ + @@ -504,7 +505,26 @@ - + + + A single parameter in a function parameter list. + + + + + + The this parameter at the first place in a parameter list. + + + + + The this keyword, representing the type instance. + + + + + + A single parameter in a function parameter list. From a8396165a28f965f37ae2143244e5dc9aa26bad3 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 3 Oct 2024 10:16:03 +0200 Subject: [PATCH 014/109] updated SyntaxFactory. --- .../Semantics/DocumentationCommentsTests.cs | 8 +- .../Semantics/FlowAnalysisTests.cs | 36 ++-- .../Semantics/LocalFunctionsTests.cs | 8 +- .../Semantics/SemanticModelTests.cs | 14 +- .../Semantics/SymbolResolutionTests.cs | 172 +++++++++--------- .../Semantics/TypeCheckingTests.cs | 96 +++++----- .../Api/Syntax/SyntaxFactory.cs | 19 +- 7 files changed, 177 insertions(+), 176 deletions(-) diff --git a/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs b/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs index b1fd1bf18..f44175566 100644 --- a/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs @@ -94,7 +94,7 @@ public void VariableDocumentationComment(string docComment) // Arrange var tree = SyntaxTree.Create(CompilationUnit( WithDocumentation(VariableDeclaration( - "x", + true, "x", null, LiteralExpression(0)), docComment))); @@ -169,14 +169,14 @@ public void ModuleDocumentationComment(string docComment) var tree = SyntaxTree.Create(CompilationUnit( WithDocumentation(ModuleDeclaration( "documentedModule", - VariableDeclaration(Api.Semantics.Visibility.Public, "Foo", null, LiteralExpression(0))), + VariableDeclaration(Api.Semantics.Visibility.Public, true, "Foo", null, LiteralExpression(0))), docComment), FunctionDeclaration( "foo", ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("documentedModule"), "Foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("documentedModule"), "Foo"))))))); var moduleRef = tree.GetNode(0).Accessed; @@ -283,7 +283,7 @@ public void StaticTypeDocumentationFromMetadata() "main", ParameterList(), null, - BlockFunctionBody(DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("TestClass"), "foo"))))))); + BlockFunctionBody(DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("TestClass"), "foo"))))))); var docs = " Documentation for TestClass "; diff --git a/src/Draco.Compiler.Tests/Semantics/FlowAnalysisTests.cs b/src/Draco.Compiler.Tests/Semantics/FlowAnalysisTests.cs index ba3ab4bf2..3ebe5b283 100644 --- a/src/Draco.Compiler.Tests/Semantics/FlowAnalysisTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/FlowAnalysisTests.cs @@ -262,8 +262,8 @@ public void ReferenceUninitializedVariable() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -289,8 +289,8 @@ public void ReferenceInitializedVariable() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"), LiteralExpression(0))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -316,9 +316,9 @@ public void ReferenceInitializedVariableAssignedLater() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -346,11 +346,11 @@ public void ReferenceVariableInitializedOnlyInOneBranch() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(IfExpression( condition: LiteralExpression(false), then: BlockExpression(ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0)))))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -382,12 +382,12 @@ public void ReferenceVariableInitializedInBothBranches() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(IfExpression( condition: LiteralExpression(false), then: BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0)), @else: BinaryExpression(NameExpression("x"), Assign, LiteralExpression(1)))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -415,12 +415,12 @@ public void ReferenceVariableInitializedOnlyInLoopBody() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(WhileExpression( condition: LiteralExpression(false), then: BlockExpression( ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0)))))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -439,7 +439,7 @@ public void GobalValInitialized() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0)))); + ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0)))); // Act var compilation = CreateCompilation(tree); @@ -463,7 +463,7 @@ public void LocalValInitialized() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0))))))); + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))))))); // Act var compilation = CreateCompilation(tree); @@ -481,7 +481,7 @@ public void GobalValNotInitialized() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - ImmutableVariableDeclaration("x", NameType("int32")))); + ImmutableVariableDeclaration(true, "x", NameType("int32")))); // Act var compilation = CreateCompilation(tree); @@ -506,7 +506,7 @@ public void LocalValNotInitialized() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"))))))); + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))))))); // Act var compilation = CreateCompilation(tree); @@ -532,7 +532,7 @@ public void LocalValReassigned() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0))), + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(1))))))); // Act @@ -555,7 +555,7 @@ public void GlobalValReassigned() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0)), + ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0)), FunctionDeclaration( "foo", ParameterList(), diff --git a/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs b/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs index de8bf9388..17df97e74 100644 --- a/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs @@ -66,7 +66,7 @@ public void UndefinedReference() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x")))))))))); + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x")))))))))); // Act var compilation = CreateCompilation(tree); @@ -98,7 +98,7 @@ public void LocalVariableIncompatibleType() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", NameType("int32"), StringExpression("Hello")))))))))); @@ -160,8 +160,8 @@ public void ReferenceUninitializedVariable() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x")))))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x")))))))))); // Act var compilation = CreateCompilation(tree); diff --git a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs index f9d446f84..4fc658be4 100644 --- a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs @@ -25,7 +25,7 @@ public void RequestingDiagnosticsAfterSymbolDoesNotDiscardDiagnostic() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")))))); + DeclarationStatement(VariableDeclaration(true, "x")))))); var xDecl = tree.GetNode(0); @@ -55,7 +55,7 @@ public void RequestingSymbolAfterDiagnosticsDoesNotDiscardDiagnostic() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")))))); + DeclarationStatement(VariableDeclaration(true, "x")))))); var xDecl = tree.GetNode(0); @@ -85,7 +85,7 @@ public void RequestingSymbolMultipleTimesDoesNotMultiplyDiagnostic() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")))))); + DeclarationStatement(VariableDeclaration(true, "x")))))); var xDecl = tree.GetNode(0); @@ -117,8 +117,8 @@ public void RequestingFunctionBodyDoesNotDiscardFlowAnalysisDiagnostic() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), - DeclarationStatement(VariableDeclaration("y", value: NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "y", value: NameExpression("x"))))))); var mainDecl = tree.GetNode(0); @@ -312,7 +312,7 @@ public void GetReferencedSymbolFromTypeMemberAccess() null, BlockFunctionBody( DeclarationStatement(ImportDeclaration("System", "Text")), - DeclarationStatement(VariableDeclaration("builder", null, CallExpression(NameExpression("StringBuilder")))), + DeclarationStatement(VariableDeclaration(true, "builder", null, CallExpression(NameExpression("StringBuilder")))), ExpressionStatement(CallExpression(MemberExpression(NameExpression("builder"), "AppendLine"))))))); var memberExprSyntax = tree.GetNode(0); @@ -350,7 +350,7 @@ public void GetReferencedSymbolFromTypeMemberAccessWithNonExistingMember() null, BlockFunctionBody( DeclarationStatement(ImportDeclaration("System", "Text")), - DeclarationStatement(VariableDeclaration("builder", null, CallExpression(NameExpression("StringBuilder")))), + DeclarationStatement(VariableDeclaration(true, "builder", null, CallExpression(NameExpression("StringBuilder")))), ExpressionStatement(CallExpression(MemberExpression(NameExpression("builder"), "Ap"))))))); var memberExprSyntax = tree.GetNode(0); diff --git a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs index d8496922c..80c365f3f 100644 --- a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs @@ -43,14 +43,14 @@ public void BasicScopeTree() Parameter("n", NameType("int32"))), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x1")), + DeclarationStatement(VariableDeclaration(true, "x1")), ExpressionStatement(BlockExpression( - DeclarationStatement(VariableDeclaration("x2")), - ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration("x3")))))), + DeclarationStatement(VariableDeclaration(true, "x2")), + ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration(true, "x3")))))), ExpressionStatement(BlockExpression( - DeclarationStatement(VariableDeclaration("x4")), - ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration("x5")))), - ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration("x6")))))))))); + DeclarationStatement(VariableDeclaration(true, "x4")), + ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration(true, "x5")))), + ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration(true, "x6")))))))))); var foo = tree.GetNode(); var n = tree.GetNode(); @@ -107,10 +107,10 @@ public void LocalShadowing() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, LiteralExpression(0))), - DeclarationStatement(VariableDeclaration("x", null, BinaryExpression(NameExpression("x"), Plus, LiteralExpression(1)))), - DeclarationStatement(VariableDeclaration("x", null, BinaryExpression(NameExpression("x"), Plus, LiteralExpression(1)))), - DeclarationStatement(VariableDeclaration("x", null, BinaryExpression(NameExpression("x"), Plus, LiteralExpression(1)))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "x", null, BinaryExpression(NameExpression("x"), Plus, LiteralExpression(1)))), + DeclarationStatement(VariableDeclaration(true, "x", null, BinaryExpression(NameExpression("x"), Plus, LiteralExpression(1)))), + DeclarationStatement(VariableDeclaration(true, "x", null, BinaryExpression(NameExpression("x"), Plus, LiteralExpression(1)))))))); var x0 = tree.GetNode(0); var x1 = tree.GetNode(1); @@ -213,9 +213,9 @@ public void OrderDependentReferencing() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")), - DeclarationStatement(VariableDeclaration("y", value: BinaryExpression(NameExpression("x"), Plus, NameExpression("z")))), - DeclarationStatement(VariableDeclaration("z")))))); + DeclarationStatement(VariableDeclaration(true, "x")), + DeclarationStatement(VariableDeclaration(true, "y", value: BinaryExpression(NameExpression("x"), Plus, NameExpression("z")))), + DeclarationStatement(VariableDeclaration(true, "z")))))); var xDecl = tree.GetNode(0); var yDecl = tree.GetNode(1); @@ -264,15 +264,15 @@ public void OrderDependentReferencingWithNesting() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")), + DeclarationStatement(VariableDeclaration(true, "x")), ExpressionStatement(BlockExpression( - DeclarationStatement(VariableDeclaration("y")), - DeclarationStatement(VariableDeclaration("z", value: BinaryExpression(NameExpression("x"), Plus, NameExpression("y")))), - DeclarationStatement(VariableDeclaration("x")), + DeclarationStatement(VariableDeclaration(true, "y")), + DeclarationStatement(VariableDeclaration(true, "z", value: BinaryExpression(NameExpression("x"), Plus, NameExpression("y")))), + DeclarationStatement(VariableDeclaration(true, "x")), ExpressionStatement(BlockExpression( - DeclarationStatement(VariableDeclaration("k", value: BinaryExpression(NameExpression("x"), Plus, NameExpression("w")))))), - DeclarationStatement(VariableDeclaration("w")))), - DeclarationStatement(VariableDeclaration("k", value: NameExpression("w"))))))); + DeclarationStatement(VariableDeclaration(true, "k", value: BinaryExpression(NameExpression("x"), Plus, NameExpression("w")))))), + DeclarationStatement(VariableDeclaration(true, "w")))), + DeclarationStatement(VariableDeclaration(true, "k", value: NameExpression("w"))))))); var x1Decl = tree.GetNode(0); var y1Decl = tree.GetNode(1); @@ -365,7 +365,7 @@ public void RedefinedParameterReference() Parameter("x", NameType("int32"))), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("y", null, NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); var x1Decl = tree.GetNode(0); var x2Decl = tree.GetNode(1); @@ -415,7 +415,7 @@ public void FuncOverloadsGlobalVar() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("b", NameType("int32")), + VariableDeclaration(true, "b", NameType("int32")), FunctionDeclaration( "b", ParameterList(Parameter("b", NameType("int32"))), @@ -455,8 +455,8 @@ public void GlobalVariableDefinedLater() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("y", value: NameExpression("x"))))), - VariableDeclaration("x"))); + DeclarationStatement(VariableDeclaration(true, "y", value: NameExpression("x"))))), + VariableDeclaration(true, "x"))); var localVarDecl = tree.GetNode(0); var globalVarDecl = tree.GetNode(1); @@ -560,8 +560,8 @@ public void GlobalCanNotReferenceGlobal() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("x", null, LiteralExpression(0)), - VariableDeclaration("y", null, NameExpression("x")))); + VariableDeclaration(true, "x", null, LiteralExpression(0)), + VariableDeclaration(true, "y", null, NameExpression("x")))); var xDecl = tree.GetNode(0); var xRef = tree.GetNode(0); @@ -588,7 +588,7 @@ public void GlobalCanReferenceFunction() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("x", null, CallExpression(NameExpression("foo"))), + VariableDeclaration(true, "x", null, CallExpression(NameExpression("foo"))), FunctionDeclaration( "foo", ParameterList(), @@ -828,7 +828,7 @@ public void ModuleIsIllegalInExpressionContext() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("a", null, NameExpression("System"))))))); + DeclarationStatement(VariableDeclaration(true, "a", null, NameExpression("System"))))))); var varDecl = tree.GetNode(0); var moduleRef = tree.GetNode(0); @@ -940,7 +940,7 @@ public void ImportIsNotAtTheTopOfFunctionBody() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "x", null, LiteralExpression(0))), DeclarationStatement(ImportDeclaration("System")))))); var importPath = tree.GetNode(0); @@ -1002,7 +1002,7 @@ public void ModuleAsVariableType() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("System"), LiteralExpression(0))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("System"), LiteralExpression(0))))))); var varTypeSyntax = tree.GetNode(0); @@ -1213,13 +1213,13 @@ public void NotVisibleGlobalVariableFullyQualified() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", type: null, value: MemberExpression(NameExpression("BarModule"), "bar")))))), + DeclarationStatement(VariableDeclaration(true, "x", type: null, value: MemberExpression(NameExpression("BarModule"), "bar")))))), ToPath("Tests", "main.draco")); // var bar = 0; var foo = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("bar", type: null, value: LiteralExpression(0))), + VariableDeclaration(true, "bar", type: null, value: LiteralExpression(0))), ToPath("Tests", "BarModule", "bar.draco")); // Act @@ -1598,14 +1598,14 @@ public void InCodeModuleImports() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("sb", null, CallExpression(NameExpression("StringBuilder")))), + DeclarationStatement(VariableDeclaration(true, "sb", null, CallExpression(NameExpression("StringBuilder")))), ExpressionStatement(CallExpression(NameExpression("WriteLine"), CallExpression(MemberExpression(NameExpression("sb"), "ToString"))))))), FunctionDeclaration( "baz", ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("sb", null, CallExpression(NameExpression("StringBuilder")))), + DeclarationStatement(VariableDeclaration(true, "sb", null, CallExpression(NameExpression("StringBuilder")))), ExpressionStatement(CallExpression(NameExpression("WriteLine"))))))); // Act @@ -1700,7 +1700,7 @@ public void ReadingAndSettingStaticFieldFullyQualified() null, BlockFunctionBody( ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("FooModule"), "foo"), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class FooModule{ @@ -1747,7 +1747,7 @@ public void ReadingAndSettingStaticFieldImported() null, BlockFunctionBody( ExpressionStatement(BinaryExpression(NameExpression("foo"), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, NameExpression("foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, NameExpression("foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class FooModule{ @@ -1792,9 +1792,9 @@ public void ReadingAndSettingNonStaticField() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("fooType"), "foo"), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -1921,7 +1921,7 @@ public void SettingReadonlyNonStaticField() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("fooType"), "foo"), Assign, LiteralExpression(5))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -1964,8 +1964,8 @@ public void ReadingNonExistingNonStaticField() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType { } @@ -2008,7 +2008,7 @@ public void SettingNonExistingNonStaticField() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("fooType"), "foo"), Assign, LiteralExpression(5))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -2087,7 +2087,7 @@ public void ReadingNonExistingStaticField() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class FooModule { } @@ -2131,7 +2131,7 @@ public void ReadingAndSettingStaticPropertyFullyQualified() null, BlockFunctionBody( ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("FooModule"), "foo"), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class FooModule{ @@ -2178,7 +2178,7 @@ public void ReadingAndSettingStaticPropertyImported() null, BlockFunctionBody( ExpressionStatement(BinaryExpression(NameExpression("foo"), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, NameExpression("foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, NameExpression("foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class FooModule{ @@ -2223,9 +2223,9 @@ public void ReadingAndSettingNonStaticProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("fooType"), "foo"), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -2311,7 +2311,7 @@ public void GettingSetOnlyStaticProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class FooModule{ @@ -2353,7 +2353,7 @@ public void SettingGetOnlyNonStaticProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("fooType"), "foo"), Assign, LiteralExpression(5))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -2396,8 +2396,8 @@ public void GettingSetOnlyNonStaticProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("fooType"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -2442,7 +2442,7 @@ public void CompoundAssignmentNonStaticProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(MemberExpression(NameExpression("fooType"), "foo"), PlusAssign, LiteralExpression(2))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -2525,9 +2525,9 @@ public void ReadingAndSettingIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(IndexExpression(NameExpression("fooType"), LiteralExpression(0)), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, IndexExpression(NameExpression("fooType"), LiteralExpression(0)))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, IndexExpression(NameExpression("fooType"), LiteralExpression(0)))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -2575,7 +2575,7 @@ public void SettingGetOnlyIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(IndexExpression(NameExpression("fooType"), LiteralExpression(0)), Assign, LiteralExpression(5))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -2616,8 +2616,8 @@ public void GettingSetOnlyIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), - DeclarationStatement(VariableDeclaration("x", null, IndexExpression(NameExpression("fooType"), LiteralExpression(0)))))))); + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, IndexExpression(NameExpression("fooType"), LiteralExpression(0)))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -2663,9 +2663,9 @@ public void ReadingAndSettingMemberAccessIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(IndexExpression(MemberExpression(NameExpression("fooType"), "foo"), LiteralExpression(0)), Assign, LiteralExpression(5))), - DeclarationStatement(VariableDeclaration("x", null, IndexExpression(MemberExpression(NameExpression("fooType"), "foo"), LiteralExpression(0)))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, IndexExpression(MemberExpression(NameExpression("fooType"), "foo"), LiteralExpression(0)))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -2718,7 +2718,7 @@ public void SettingGetOnlyMemberAccessIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(IndexExpression(MemberExpression(NameExpression("fooType"), "foo"), LiteralExpression(0)), Assign, LiteralExpression(5))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -2762,8 +2762,8 @@ public void GettingSetOnlyMemberAccessIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("fooType", null, CallExpression(NameExpression("FooType")))), - DeclarationStatement(VariableDeclaration("x", null, IndexExpression(MemberExpression(NameExpression("fooType"), "foo"), LiteralExpression(0)))))))); + DeclarationStatement(VariableDeclaration(true, "fooType", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, IndexExpression(MemberExpression(NameExpression("fooType"), "foo"), LiteralExpression(0)))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType{ @@ -2813,8 +2813,8 @@ public void GettingNonExistingIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("FooType")))), - DeclarationStatement(VariableDeclaration("x", null, IndexExpression(NameExpression("foo"), LiteralExpression(0)))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, IndexExpression(NameExpression("foo"), LiteralExpression(0)))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType { } @@ -2857,7 +2857,7 @@ public void SettingNonExistingIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(IndexExpression(NameExpression("foo"), LiteralExpression(0)), Assign, LiteralExpression(5))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -2896,7 +2896,7 @@ public void CompoundAssignmentIndexer() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("FooType")))), ExpressionStatement(BinaryExpression(IndexExpression(NameExpression("foo"), LiteralExpression(0)), PlusAssign, LiteralExpression(2))))))); var fooRef = CompileCSharpToMetadataReference(""" @@ -3061,7 +3061,7 @@ public void NestedTypeWithStaticParentStaticMemberAccess() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(MemberExpression(NameExpression("ParentType"), "FooType"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(MemberExpression(NameExpression("ParentType"), "FooType"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class ParentType @@ -3106,7 +3106,7 @@ public void NestedTypeWithNonStaticParentStaticMemberAccess() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(MemberExpression(NameExpression("ParentType"), "FooType"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(MemberExpression(NameExpression("ParentType"), "FooType"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class ParentType @@ -3152,8 +3152,8 @@ public void NestedTypeWithStaticParentNonStaticMemberAccess() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(MemberExpression(NameExpression("ParentType"), "FooType")))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("foo"), "member"))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(MemberExpression(NameExpression("ParentType"), "FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("foo"), "member"))))))); var fooRef = CompileCSharpToMetadataReference(""" public static class ParentType @@ -3202,8 +3202,8 @@ public void NestedTypeWithNonStaticParentNonStaticMemberAccess() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(MemberExpression(NameExpression("ParentType"), "FooType")))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("foo"), "member"))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(MemberExpression(NameExpression("ParentType"), "FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("foo"), "member"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class ParentType @@ -3288,7 +3288,7 @@ public void InheritanceFromObject() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType { } @@ -3329,7 +3329,7 @@ public void InheritanceFromTypeDefinition() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var fooRef = CompileCSharpToMetadataReference(""" public class ParentType { } @@ -3372,7 +3372,7 @@ public void InheritanceFromNestedTypeReference() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var baseStream = CompileCSharpToStream(""" public class ParentType @@ -3425,7 +3425,7 @@ public void InheritanceFromTypeSpecification() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var fooRef = CompileCSharpToMetadataReference(""" public class ParentType { } @@ -3473,7 +3473,7 @@ public void InheritingInterfacesFromTypeDefinition() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var fooRef = CompileCSharpToMetadataReference(""" public interface ParentInterface { } @@ -3517,7 +3517,7 @@ public void InheritingInterfacesFromTypeReference() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var fooRef = CompileCSharpToMetadataReference(""" public class FooType : System.ICloneable @@ -3562,7 +3562,7 @@ public void InheretingInterfaceFromTypeSpecification() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression((NameExpression("FooType"))))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression((NameExpression("FooType"))))))))); var fooRef = CompileCSharpToMetadataReference(""" public interface ParentInterface { } @@ -3612,8 +3612,8 @@ public void AccessingMemberOfBaseType() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("FooType")))), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("foo"), "Field"))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("FooType")))), + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("foo"), "Field"))))))); var fooRef = CompileCSharpToMetadataReference(""" public class ParentType @@ -3659,7 +3659,7 @@ public void ImplicitOverrideFunction() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("Derived")))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("Derived")))))))); var fooRef = CompileCSharpToMetadataReference(""" public class Base @@ -3708,7 +3708,7 @@ public void ExplicitOverrideFunctionInSameAssembly() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("Derived")))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("Derived")))))))); var fooRef = CompileCSharpToMetadataReference(""" public class Base @@ -3757,7 +3757,7 @@ public void ExplicitOverrideFunctionInDifferentAssembly() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("Derived")))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("Derived")))))))); var baseStream = CompileCSharpToStream(""" public class Base @@ -3812,7 +3812,7 @@ public void ImplicitOverrideProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("Derived")))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("Derived")))))))); var fooRef = CompileCSharpToMetadataReference(""" public class Base @@ -3861,7 +3861,7 @@ public void ExplicitOverrideProperty() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("foo", null, CallExpression(NameExpression("Derived")))))))); + DeclarationStatement(VariableDeclaration(true, "foo", null, CallExpression(NameExpression("Derived")))))))); var fooRef = CompileCSharpToMetadataReference(""" public class Base diff --git a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs index 297820e92..c0796a672 100644 --- a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs @@ -21,7 +21,7 @@ public void LocalVariableExplicitlyTyped() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"), LiteralExpression(0))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))))))); var xDecl = tree.GetNode(0); @@ -49,7 +49,7 @@ public void LocalVariableTypeInferredFromValue() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", value: LiteralExpression(0))))))); + DeclarationStatement(VariableDeclaration(true, "x", value: LiteralExpression(0))))))); var xDecl = tree.GetNode(0); @@ -77,7 +77,7 @@ public void LocalVariableExplicitlyTypedWithoutValue() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))))))); var xDecl = tree.GetNode(0); @@ -106,7 +106,7 @@ public void LocalVariableTypeInferredFromLaterAssignment() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")), + DeclarationStatement(VariableDeclaration(true, "x")), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0))))))); var xDecl = tree.GetNode(0); @@ -135,7 +135,7 @@ public void LocalVariableTypeCanNotBeInferred() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")))))); + DeclarationStatement(VariableDeclaration(true, "x")))))); var xDecl = tree.GetNode(0); @@ -166,7 +166,7 @@ public void LocalVariableIncompatibleType() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", NameType("int32"), StringExpression("Hello"))))))); @@ -200,7 +200,7 @@ public void LocalVariableIncompatibleTypeInferredFromUsage() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x")), + DeclarationStatement(VariableDeclaration(true, "x")), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0))), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, StringExpression("Hello"))))))); @@ -226,7 +226,7 @@ public void GlobalVariableExplicitlyTyped() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("x", NameType("int32"), LiteralExpression(0)))); + VariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0)))); var xDecl = tree.GetNode(0); @@ -248,7 +248,7 @@ public void GlobalVariableTypeInferredFromValue() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("x", value: LiteralExpression(0)))); + VariableDeclaration(true, "x", value: LiteralExpression(0)))); var xDecl = tree.GetNode(0); @@ -270,7 +270,7 @@ public void GlobalVariableExplicitlyTypedWithoutValue() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("x", NameType("int32")))); + VariableDeclaration(true, "x", NameType("int32")))); var xDecl = tree.GetNode(0); @@ -292,7 +292,7 @@ public void GlobalVariableTypeCanNotBeInferred() // Arrange var tree = SyntaxTree.Create(CompilationUnit( - VariableDeclaration("x"))); + VariableDeclaration(true, "x"))); var xDecl = tree.GetNode(0); @@ -317,7 +317,7 @@ public void GlobalVariableIncompatibleType() // Arrange var tree = SyntaxTree.Create(CompilationUnit( VariableDeclaration( - "x", + true, "x", NameType("int32"), StringExpression("Hello")))); @@ -495,7 +495,7 @@ public void IfElseTypeMismatch() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", value: IfExpression( condition: LiteralExpression(true), then: LiteralExpression(0), @@ -568,8 +568,8 @@ public void NeverTypeCompatibility() null, BlockFunctionBody( DeclarationStatement(LabelDeclaration("start")), - DeclarationStatement(VariableDeclaration("x", value: IfExpression(LiteralExpression(true), LiteralExpression(0), ReturnExpression()))), - DeclarationStatement(VariableDeclaration("y", value: IfExpression(LiteralExpression(true), LiteralExpression(0), GotoExpression("start")))))))); + DeclarationStatement(VariableDeclaration(true, "x", value: IfExpression(LiteralExpression(true), LiteralExpression(0), ReturnExpression()))), + DeclarationStatement(VariableDeclaration(true, "y", value: IfExpression(LiteralExpression(true), LiteralExpression(0), GotoExpression("start")))))))); var xDecl = tree.GetNode(0); var yDecl = tree.GetNode(1); @@ -603,7 +603,7 @@ public void NoOverloadForOperator() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", value: BinaryExpression(LiteralExpression(1), Plus, StringExpression("Hello")))))))); var xDecl = tree.GetNode(0); @@ -1056,7 +1056,7 @@ public void AccessingField() null, BlockFunctionBody( DeclarationStatement(ImportDeclaration("System")), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("String"), "Empty"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("String"), "Empty"))))))); var xDecl = tree.GetNode(0); var consoleRef = tree.GetNode(0).Accessed; @@ -1089,7 +1089,7 @@ public void AccessingProperty() null, BlockFunctionBody( DeclarationStatement(ImportDeclaration("System")), - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("Console"), "WindowWidth"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("Console"), "WindowWidth"))))))); var xDecl = tree.GetNode(0); var consoleRef = tree.GetNode(0).Accessed; @@ -1123,8 +1123,8 @@ public void AccessingIndexer() null, BlockFunctionBody( DeclarationStatement(ImportDeclaration("System", "Collections", "Generic")), - DeclarationStatement(VariableDeclaration("list", null, CallExpression(GenericExpression(NameExpression("List"), NameType("int32"))))), - DeclarationStatement(VariableDeclaration("x", null, IndexExpression(NameExpression("list"), LiteralExpression(0)))))))); + DeclarationStatement(VariableDeclaration(true, "list", null, CallExpression(GenericExpression(NameExpression("List"), NameType("int32"))))), + DeclarationStatement(VariableDeclaration(true, "x", null, IndexExpression(NameExpression("list"), LiteralExpression(0)))))))); var xDecl = tree.GetNode(1); var listRef = tree.GetNode(0).Indexed; @@ -1157,7 +1157,7 @@ public void IllegalCallToNonFunctionType() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("a", null, LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "a", null, LiteralExpression(0))), ExpressionStatement(CallExpression(NameExpression("a"))))))); // Act @@ -1196,19 +1196,19 @@ public void ExplicitGenericFunction() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "a", + true, "a", null, CallExpression( GenericExpression(NameExpression("identity"), NameType("int32")), LiteralExpression(0)))), DeclarationStatement(VariableDeclaration( - "b", + true, "b", null, CallExpression( GenericExpression(NameExpression("identity"), NameType("string")), StringExpression("foo")))), DeclarationStatement(VariableDeclaration( - "c", + true, "c", null, CallExpression( GenericExpression(NameExpression("identity"), NameType("int32")), @@ -1274,7 +1274,7 @@ public void ExplicitGenericFunctionWithWrongNumberOfArgs() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "a", + true, "a", null, CallExpression( GenericExpression(NameExpression("identity"), NameType("int32"), NameType("int32")), @@ -1306,7 +1306,7 @@ public void InstantiateIllegalConstruct() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("a", null, LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "a", null, LiteralExpression(0))), ExpressionStatement(CallExpression(GenericExpression(NameExpression("a"), NameType("int32")))))))); // Act @@ -1330,7 +1330,7 @@ public void ExplicitGenericTypeWithWrongNumberOfArgs() var tree = SyntaxTree.Create(CompilationUnit( ImportDeclaration("System", "Collections", "Generic"), VariableDeclaration( - "l", + true, "l", GenericType(NameType("List"), NameType("int32"), NameType("int32"))))); // Act @@ -1367,7 +1367,7 @@ public void InferGenericFunctionParameterTypeFromUse() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", null, CallExpression(NameExpression("identity"), LiteralExpression(0)))))))); @@ -1409,7 +1409,7 @@ public void InferGenericCollectionTypeFromUse() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("s", null, CallExpression(NameExpression("Stack")))), + DeclarationStatement(VariableDeclaration(true, "s", null, CallExpression(NameExpression("Stack")))), ExpressionStatement(CallExpression( MemberExpression(NameExpression("s"), "Push"), LiteralExpression(0))))))); @@ -1452,7 +1452,7 @@ public void CanNotInferGenericCollectionTypeFromUse() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("s", null, CallExpression(NameExpression("Stack")))))))); + DeclarationStatement(VariableDeclaration(true, "s", null, CallExpression(NameExpression("Stack")))))))); var callSyntax = tree.GetNode(); var varSyntax = tree.GetNode(); @@ -1809,7 +1809,7 @@ public void AssignDerivedTypeToBaseType() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("Object"), CallExpression(NameExpression("Random")))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("Object"), CallExpression(NameExpression("Random")))))))); var xDecl = main.GetNode(0); @@ -1842,7 +1842,7 @@ public void AssignBaseTypeToDerivedType() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("String"), CallExpression(NameExpression("Object")))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("String"), CallExpression(NameExpression("Object")))))))); var xDecl = main.GetNode(0); @@ -2056,7 +2056,7 @@ public void IfStatementCommonTypeResult() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", null, IfExpression( LiteralExpression(true), @@ -2096,18 +2096,18 @@ public void InferSwappedArrayElement() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "a", + true, "a", null, CallExpression(NameExpression("Array"), LiteralExpression(5)))), DeclarationStatement(VariableDeclaration( - "b", + true, "b", null, CallExpression(NameExpression("Array"), LiteralExpression(5)))), ExpressionStatement(BinaryExpression( IndexExpression(NameExpression("a"), LiteralExpression(0)), Assign, LiteralExpression(1))), - DeclarationStatement(ImmutableVariableDeclaration("tmp", null, NameExpression("a"))), + DeclarationStatement(ImmutableVariableDeclaration(true, "tmp", null, NameExpression("a"))), ExpressionStatement(BinaryExpression(NameExpression("a"), Assign, NameExpression("b"))), ExpressionStatement(BinaryExpression(NameExpression("b"), Assign, NameExpression("tmp"))))))); @@ -2151,8 +2151,8 @@ public void IndexerWitingOverloadedCall() NameType("int32"), BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration( - "line", - null, + true, + "line", null, CallExpression(MemberExpression(NameExpression("Console"), "ReadLine")))), ExpressionStatement(ReturnExpression( CallExpression( @@ -2184,7 +2184,7 @@ public void GettingTypeFromReference() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); + DeclarationStatement(VariableDeclaration(true, "x", null, MemberExpression(NameExpression("FooModule"), "foo"))))))); var fooRef = CompileCSharpToMetadataReference(""" using System; @@ -2223,7 +2223,7 @@ public void StringAssignableToObject() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - "x", + true, "x", NameType("object"), StringExpression("Hello"))))))); @@ -2252,8 +2252,8 @@ public void InferredArrayElementTypeFromUsage() null, BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration( - "a", - null, + true, + "a", null, CallExpression( NameExpression("Array"), LiteralExpression(5)))), @@ -2291,12 +2291,12 @@ public void ArrayIndexResultHasTheRightType() null, BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration( - "a", - null, + true, + "a", null, CallExpression(GenericExpression(NameExpression("Array"), NameType("int32")), LiteralExpression(3)))), DeclarationStatement(ImmutableVariableDeclaration( - "x", - null, + true, + "x", null, IndexExpression(NameExpression("a"), LiteralExpression(0)))))))); // Act @@ -2327,8 +2327,8 @@ public void ArrayIteratorVariableCorrectlyInferredInForLoop() null, BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration( - "a", - null, + true, + "a", null, CallExpression(GenericExpression(NameExpression("Array"), NameType("int32")), LiteralExpression(3)))), ExpressionStatement(ForExpression( "x", diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index 1c1b5f0fe..197ef7fce 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -167,36 +167,37 @@ public static FunctionDeclarationSyntax FunctionDeclaration( body); public static VariableDeclarationSyntax VariableDeclaration( + bool globql, string name, - TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(null, null, true, name, type, value); + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(null, globql, true, name, type, value); public static VariableDeclarationSyntax VariableDeclaration( Visibility visibility, + bool globql, string name, - TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), null, true, name, type, value); + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), globql, true, name, type, value); public static VariableDeclarationSyntax ImmutableVariableDeclaration( + bool global, string name, - TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(null, null, false, name, type, value); + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(null, global, false, name, type, value); public static VariableDeclarationSyntax ImmutableVariableDeclaration( Visibility visibility, + bool global, string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), null, false, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), global, false, name, type, value); public static VariableDeclarationSyntax VariableDeclaration( TokenKind? visibility, - TokenKind? global, + bool global, bool isMutable, string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration( [], visibility, - global, + global ? TokenKind.KeywordGlobal : null, isMutable ? TokenKind.KeywordVar : TokenKind.KeywordVal, name, type is null ? null : TypeSpecifier(type), From 0521fa4ad5b66b3c9ff4f2a83a54c34fd07e521a Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 3 Oct 2024 23:29:01 +0200 Subject: [PATCH 015/109] ps swap. --- .../EndToEnd/CodeExecutionTests.cs | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index 2d0512a21..ae1418951 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -21,7 +21,7 @@ func main() { } class Foo { - global func bar() { + func bar() { WriteLine("Hello, World!"); } } @@ -32,4 +32,24 @@ global func bar() { Assert.Equal($"Hello, World!{Environment.NewLine}", stringWriter.ToString(), ignoreLineEndingDifferences: true); } + + [Fact] + public void InstanceField() + { + var assembly = CompileToAssembly(""" + import System.Console; + + func main() { + var foo = Foo(); + } + + class Foo { + i: int; + increment(this): void { + this.i += 1; + } + } + + """); + } } From 3c638458e6fa54fa3cf14ecdc902ec5fefcb4c2d Mon Sep 17 00:00:00 2001 From: Kuinox Date: Fri, 4 Oct 2024 00:53:30 +0200 Subject: [PATCH 016/109] use field keyword. --- src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index ae1418951..4b7d33889 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -44,7 +44,7 @@ func main() { } class Foo { - i: int; + field i: int; increment(this): void { this.i += 1; } From ca84c41b2a4ccf019c771c4417f72f708c047abc Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sat, 5 Oct 2024 17:44:20 +0200 Subject: [PATCH 017/109] wip --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 28 +++++++++++++------ .../Internal/Syntax/SyntaxErrors.cs | 9 ++++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 628a87311..4c56176dd 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -380,7 +380,8 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordModule: return this.ParseModuleDeclaration(attributes, visibility, context); - + case TokenKind.KeywordField: + return this.ParseFieldDeclaration(attributes, visibility, context); case TokenKind.KeywordVar: case TokenKind.KeywordVal: return this.ParseVariableDeclaration(attributes, visibility, global, context); @@ -554,15 +555,12 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, Sy /// Parses the body of a class. /// /// The parsed . - private ClassBodySyntax ParseClassBody() + private ClassBodySyntax ParseClassBody() => this.PeekKind() switch { - return this.PeekKind() switch - { - TokenKind.Semicolon => this.ParseEmptyClassBody(), - TokenKind.CurlyOpen => this.ParseBlockClassBody(), - _ => throw new NotImplementedException(),// TODO - }; - } + TokenKind.Semicolon => this.ParseEmptyClassBody(), + TokenKind.CurlyOpen => this.ParseBlockClassBody(), + _ => throw new NotImplementedException(),// TODO + }; /// /// Parses an empty class body, which is just a semicolon. @@ -638,6 +636,18 @@ private VariableDeclarationSyntax ParseVariableDeclaration( return new VariableDeclarationSyntax(attributes, visibility, global, keyword, identifier, type, assignment, semicolon); } + private FieldDeclarationSyntax ParseFieldDeclaration( + SyntaxList? attributes, + SyntaxToken? visibility, + SyntaxToken? global, + DeclarationContext context) + { + if(context == DeclarationContext.Local) + { + var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedFieldDeclarationInFunction) + } + } + /// /// Parses a function declaration. /// diff --git a/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs b/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs index 2a18f5baf..1ff2fbdfe 100644 --- a/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs +++ b/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs @@ -171,4 +171,13 @@ internal static class SyntaxErrors severity: DiagnosticSeverity.Error, format: "{0} is not a valid {1} in Draco, use {2} instead", code: Code(18)); + + /// + /// There is a field declaration in a function. + /// + public static readonly DiagnosticTemplate UnexpectedFieldDeclarationInFunction = DiagnosticTemplate.Create( + title: "unexpected field declaration", + severity: DiagnosticSeverity.Error, + format: "unexpected field declaration", + code: Code(19)); } From 0476eac41ae6b8fab2317db6a327b58db2ab6324 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sat, 5 Oct 2024 17:49:14 +0200 Subject: [PATCH 018/109] wip --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 4c56176dd..50b4c4cf2 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -644,7 +644,8 @@ private FieldDeclarationSyntax ParseFieldDeclaration( { if(context == DeclarationContext.Local) { - var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedFieldDeclarationInFunction) + var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedFieldDeclarationInFunction); + this.AddDiagnostic() } } From 940f5f89e48025d32e461dc3cbf9b599aefb6821 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Tue, 8 Oct 2024 01:02:08 +0200 Subject: [PATCH 019/109] starting to implementing this. --- .../EndToEnd/CodeExecutionTests.cs | 2 +- .../Api/Syntax/SyntaxFactory.cs | 14 ++--- .../Internal/Binding/Binder_Expression.cs | 10 ++++ .../Internal/Binding/Binder_Lookup.cs | 23 ++++++++ .../Internal/Binding/Binder_Type.cs | 2 +- .../Internal/Binding/ClassBinder.cs | 4 +- .../Binding/SymbolResolutionErrors.cs | 12 ++++ .../Internal/BoundTree/BoundNodes.xml | 4 ++ .../Source/SourceThisParameterSymbol.cs | 17 ++++++ .../Symbols/Syntax/SyntaxFunctionSymbol.cs | 26 ++++++++- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 3 +- src/Draco.Compiler/Internal/Syntax/Parser.cs | 56 ++++++++++++++++--- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 24 +++++++- 13 files changed, 174 insertions(+), 23 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index 4b7d33889..2efacaec6 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -45,7 +45,7 @@ func main() { class Foo { field i: int; - increment(this): void { + func increment(this) { this.i += 1; } } diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index 197ef7fce..66423a738 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -91,9 +91,9 @@ public static SeparatedSyntaxList SeparatedSyntaxList(SyntaxToken public static SeparatedSyntaxList SeparatedSyntaxList(SyntaxToken separator, params TNode[] elements) where TNode : SyntaxNode => SeparatedSyntaxList(separator, elements.AsEnumerable()); - public static SeparatedSyntaxList ParameterList(IEnumerable parameters) => + public static SeparatedSyntaxList ParameterList(IEnumerable parameters) => SeparatedSyntaxList(Comma, parameters); - public static SeparatedSyntaxList ParameterList(params ParameterSyntax[] parameters) => + public static SeparatedSyntaxList ParameterList(params ParameterSyntaxBase[] parameters) => SeparatedSyntaxList(Comma, parameters); public static ParameterSyntax Parameter(string name, TypeSyntax type) => Parameter([], name, type); @@ -121,7 +121,7 @@ public static ImportDeclarationSyntax ImportDeclaration(string root, params stri public static FunctionDeclarationSyntax FunctionDeclaration( string name, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration([], Semantics.Visibility.Private, name, null, parameters, returnType, body); @@ -129,7 +129,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( IEnumerable attributes, string name, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration(attributes, Semantics.Visibility.Private, name, null, parameters, returnType, body); @@ -137,7 +137,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( Visibility visibility, string name, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration([], visibility, name, null, parameters, returnType, body); @@ -145,7 +145,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( string name, GenericParameterListSyntax? generics, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration([], Semantics.Visibility.Private, name, generics, parameters, returnType, body); @@ -155,7 +155,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( Visibility visibility, string name, GenericParameterListSyntax? generics, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration( attributes, diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index 24365b3af..fe86c2ebc 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -47,6 +47,7 @@ internal partial class Binder MemberExpressionSyntax maccess => this.BindMemberExpression(maccess, constraints, diagnostics), GenericExpressionSyntax gen => this.BindGenericExpression(gen, constraints, diagnostics), IndexExpressionSyntax index => this.BindIndexExpression(index, constraints, diagnostics), + ThisExpressionSyntax @this => this.BindThisExpression(@this, constraints, diagnostics), _ => throw new ArgumentOutOfRangeException(nameof(syntax)), }; @@ -678,6 +679,15 @@ private async BindingTask BindIndexExpression(IndexExpressionSy } } + private BindingTask BindThisExpression(ThisExpressionSyntax @this, ConstraintSolver constraints, DiagnosticBag diagnostics) + { + var declaringType = this.LookupDeclaringType(@this, diagnostics); + + var boundThis = new BoundThisExpression(@this, declaringType); + return BindingTask.FromResult(boundThis); + } + + private async BindingTask BindGenericExpression(GenericExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { var instantiatedTask = this.BindExpression(syntax.Instantiated, constraints, diagnostics); diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs b/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs index 2ecafccde..125dfe987 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs @@ -2,11 +2,13 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Diagnostics; using Draco.Compiler.Internal.Solver; using Draco.Compiler.Internal.Solver.Tasks; using Draco.Compiler.Internal.Symbols; +using Draco.Compiler.Internal.Symbols.Error; using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.Binding; @@ -51,6 +53,27 @@ internal Symbol LookupTypeSymbol(string name, SyntaxNode reference, DiagnosticBa var result = this.LookupInternal(name, BinderFacts.IsTypeSymbol, reference); return result.GetType(name, reference, diagnostics); } + /// + /// Looks up the declaring type of the current scope. + /// + /// The syntax referencing the symbol. + /// The diagnostics are added here from lookup. + /// + /// + internal TypeSymbol LookupDeclaringType(SyntaxNode reference, DiagnosticBag diagnostics) + { + foreach (var scope in this.AncestorChain) + { + if (scope is ClassBinder classBinder) + { + return classBinder.ContainingSymbol; + } + } + diagnostics.Add(Diagnostic.Create( + template: SymbolResolutionErrors.NoTypeInstanceToReference, + location: reference.Location)); + return WellKnownTypes.ErrorType; + } /// /// Looks up a symbol that can be used in label-context. diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Type.cs b/src/Draco.Compiler/Internal/Binding/Binder_Type.cs index c24f5f616..8c72aa299 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Type.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Type.cs @@ -51,7 +51,7 @@ internal TypeSymbol BindTypeToTypeSymbol(TypeSyntax syntax, DiagnosticBag diagno internal virtual Symbol BindType(TypeSyntax syntax, DiagnosticBag diagnostics) => syntax switch { // NOTE: The syntax error is already reported - UnexpectedTypeSyntax => new ErrorTypeSymbol(""), + UnexpectedTypeSyntax => WellKnownTypes.ErrorType, NameTypeSyntax name => this.BindNameType(name, diagnostics), MemberTypeSyntax member => this.BindMemberType(member, diagnostics), GenericTypeSyntax generic => this.BindGenericType(generic, diagnostics), diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs index 7b4cf9f7b..e8849b458 100644 --- a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -10,10 +10,10 @@ namespace Draco.Compiler.Internal.Binding; internal sealed class ClassBinder(Binder parent, TypeSymbol symbol) : Binder(parent) { - public override Symbol? ContainingSymbol => this.symbol; + public override TypeSymbol ContainingSymbol => this.symbol; public override SyntaxNode? DeclaringSyntax => this.symbol.DeclaringSyntax; - private readonly Symbol symbol = symbol; + private readonly TypeSymbol symbol = symbol; public override IEnumerable DeclaredSymbols => this.symbol.Members .Cast() diff --git a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs index d57f401d2..0be99499c 100644 --- a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs +++ b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs @@ -182,4 +182,16 @@ internal static class SymbolResolutionErrors severity: DiagnosticSeverity.Error, format: "the {0} {1} is inaccessible due to its visibility", code: Code(19)); + + public static readonly DiagnosticTemplate ThisParameterNotFirst = DiagnosticTemplate.Create( + title: "this parameter not first", + severity: DiagnosticSeverity.Error, + format: "the this parameter must be the first parameter", + code: Code(20)); + + public static readonly DiagnosticTemplate NoTypeInstanceToReference = DiagnosticTemplate.Create( + title: "no type instance to reference", + severity: DiagnosticSeverity.Error, + format: "there is no type instance to reference.", + code: Code(21)); } diff --git a/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml b/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml index c0fca7351..4ec161676 100644 --- a/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml +++ b/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml @@ -191,6 +191,10 @@ + + + + diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs new file mode 100644 index 000000000..31af4fec1 --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Immutable; +using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Binding; + +namespace Draco.Compiler.Internal.Symbols.Source; + +internal sealed class SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterSyntax syntax) : ParameterSymbol +{ + public override string Name => "this"; + public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; + public override bool IsVariadic => false; + public override ThisParameterSyntax DeclaringSyntax { get; } = syntax; + + public override ImmutableArray Attributes => []; + public override TypeSymbol Type { get; } = (containingSymbol.ContainingSymbol as TypeSymbol)!; +} diff --git a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs index 6978942df..cdb7009d1 100644 --- a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs @@ -1,5 +1,6 @@ using System.Collections.Immutable; using System.Linq; +using System.Reflection.Metadata.Ecma335; using System.Threading; using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; @@ -98,9 +99,28 @@ private ImmutableArray BindParameters(IBinderProvider binderPro var parameterSyntaxes = this.DeclaringSyntax.ParameterList.Values.ToList(); var parameters = ImmutableArray.CreateBuilder(); + var isInstance = null as SourceThisParameterSymbol; + for (var i = 0; i < parameterSyntaxes.Count; ++i) { - var parameterSyntax = parameterSyntaxes[i]; + var syntax = parameterSyntaxes[i]; + + if (syntax is ThisParameterSyntax thisParameter) + { + var asSymbol = new SourceThisParameterSymbol(this, thisParameter); + if (i == 0) + { + isInstance = asSymbol; + continue; + } + binderProvider.DiagnosticBag.Add(Diagnostic.Create( + template: SymbolResolutionErrors.ThisParameterNotFirst, + location: thisParameter.Location)); + parameters.Add(asSymbol); + continue; + } + var parameterSyntax = (ParameterSyntax)syntax; + var parameterName = parameterSyntax.Name.Text; var usedBefore = parameters.Any(p => p.Name == parameterName); @@ -109,7 +129,7 @@ private ImmutableArray BindParameters(IBinderProvider binderPro // NOTE: We only report later duplicates, no need to report the first instance binderProvider.DiagnosticBag.Add(Diagnostic.Create( template: SymbolResolutionErrors.IllegalShadowing, - location: parameterSyntax.Location, + location: syntax.Location, formatArgs: parameterName)); } @@ -117,7 +137,7 @@ private ImmutableArray BindParameters(IBinderProvider binderPro { binderProvider.DiagnosticBag.Add(Diagnostic.Create( template: SymbolResolutionErrors.VariadicParameterNotLast, - location: parameterSyntax.Location, + location: syntax.Location, formatArgs: parameterName)); } diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index afd48f15a..71a2d1690 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -331,9 +331,9 @@ Unit TakeWithText(TokenKind tokenKind, int length) { "and" => TokenKind.KeywordAnd, "class" => TokenKind.KeywordClass, - "this" => TokenKind.KeywordThis, "else" => TokenKind.KeywordElse, "false" => TokenKind.KeywordFalse, + "field" => TokenKind.KeywordField, "for" => TokenKind.KeywordFor, "func" => TokenKind.KeywordFunc, "goto" => TokenKind.KeywordGoto, @@ -348,6 +348,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) "public" => TokenKind.KeywordPublic, "rem" => TokenKind.KeywordRem, "return" => TokenKind.KeywordReturn, + "this" => TokenKind.KeywordThis, "true" => TokenKind.KeywordTrue, "val" => TokenKind.KeywordVal, "value" => TokenKind.KeywordValue, diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 50b4c4cf2..4317b1e40 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -223,6 +223,7 @@ private ExpressionParserDelegate BinaryRight(params TokenKind[] operators) => le TokenKind.Plus, TokenKind.Minus, TokenKind.Star, + TokenKind.KeywordThis ]; /// @@ -381,7 +382,7 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordModule: return this.ParseModuleDeclaration(attributes, visibility, context); case TokenKind.KeywordField: - return this.ParseFieldDeclaration(attributes, visibility, context); + return this.ParseFieldDeclaration(attributes, visibility, global, context); case TokenKind.KeywordVar: case TokenKind.KeywordVal: return this.ParseVariableDeclaration(attributes, visibility, global, context); @@ -596,8 +597,8 @@ private BlockClassBodySyntax ParseBlockClassBody() /// /// Parses a . /// - /// The attributes on the import. - /// The visibility modifier on the import. + /// The attributes on the variable. + /// The visibility modifier on the variable. /// The current declaration context. /// The parsed . private VariableDeclarationSyntax ParseVariableDeclaration( @@ -636,17 +637,44 @@ private VariableDeclarationSyntax ParseVariableDeclaration( return new VariableDeclarationSyntax(attributes, visibility, global, keyword, identifier, type, assignment, semicolon); } + + /// + /// Parses a . + /// + /// The attributes on the field. + /// The visibility modifier on the field. + /// The current declaration context. + /// The parsed . private FieldDeclarationSyntax ParseFieldDeclaration( SyntaxList? attributes, SyntaxToken? visibility, SyntaxToken? global, DeclarationContext context) { - if(context == DeclarationContext.Local) + // NOTE: We will always call this function by checking the leading keyword + var keyword = this.Advance(); + var identifier = this.Expect(TokenKind.Identifier); + // We don't necessarily have type specifier + TypeSpecifierSyntax? type = null; + if (this.PeekKind() == TokenKind.Colon) type = this.ParseTypeSpecifier(); + // We don't necessarily have value assigned to the variable + ValueSpecifierSyntax? assignment = null; + if (this.Matches(TokenKind.Assign, out var assign)) + { + var value = this.ParseExpression(); + assignment = new(assign, value); + } + + // Eat semicolon at the end of declaration + var semicolon = this.Expect(TokenKind.Semicolon); + + var syntax = new FieldDeclarationSyntax(attributes, visibility, keyword, identifier, type, assignment, semicolon); + if (context == DeclarationContext.Local) { var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedFieldDeclarationInFunction); - this.AddDiagnostic() + this.AddDiagnostic(syntax, info); } + return syntax; } /// @@ -807,14 +835,23 @@ private DeclarationSyntax ParseLabelDeclaration( /// Parses a function parameter. /// /// The parsed . - private ParameterSyntax ParseParameter() + private ParameterSyntaxBase ParseParameter() { var attributes = this.ParseAttributeList(); + if (this.Matches(TokenKind.KeywordThis, out var thisKeyWord)) + { + if (attributes is not null) + { + var diag = DiagnosticInfo.Create(SyntaxErrors.UnexpectedAttributeList, formatArgs: "this parameter"); + this.AddDiagnostic(attributes, diag); + } + return new ThisParameterSyntax(thisKeyWord); + } this.Matches(TokenKind.Ellipsis, out var variadic); var name = this.Expect(TokenKind.Identifier); var colon = this.Expect(TokenKind.Colon); var type = this.ParseType(); - return new(attributes, variadic, name, colon, type); + return new ParameterSyntax(attributes, variadic, name, colon, type); } /// @@ -1313,6 +1350,11 @@ private ExpressionSyntax ParseAtomExpression(int level) var value = this.Advance(); return new LiteralExpressionSyntax(value); } + case TokenKind.KeywordThis: + { + var keyword = this.Advance(); + return new ThisExpressionSyntax(keyword); + } case TokenKind.LineStringStart: return this.ParseLineString(); case TokenKind.MultiLineStringStart: diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 5196b59b0..7b6b73c58 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -481,7 +481,7 @@ - + The parameters this function declares. @@ -534,6 +534,7 @@ The attributes of this parameter. + The ellipsis token, in case it's variadic. @@ -730,6 +731,13 @@ A field declaration. + + + The attributes of this field. + + + + The visibility modifier keyword possibly starting the declaration. @@ -1414,6 +1422,20 @@ + + + The keyword this, representing the type instance. + + + + + The this keyword. + + + + + + An expression between parenthesis. From 929d8754682ab1beb6f74b4fe84ac51f0de43499 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Tue, 8 Oct 2024 22:23:48 +0200 Subject: [PATCH 020/109] fix --- src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs index 6804e92e3..452adcf99 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -19,6 +19,7 @@ private TypeSymbol BindTypeIfNeeded(IBinderProvider binder) => private TypeSymbol? type; public override bool IsMutable => this.DeclaringSyntax.Keyword.Kind == TokenKind.KeywordVar; + public override string Name => this.DeclaringSyntax.Name.Text; public override FieldDeclarationSyntax DeclaringSyntax { get; } = field; From 4d404abfb613c947635b20af65e5a95072f643bd Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 9 Oct 2024 00:10:44 +0200 Subject: [PATCH 021/109] wip --- .../EndToEnd/CodeExecutionTests.cs | 2 +- .../Syntax/ParserTests.cs | 14 ++--- .../Api/Syntax/SyntaxFactory.cs | 17 +++--- .../Internal/Binding/BinderFacts.cs | 1 - .../Internal/Binding/LocalBinder.cs | 5 +- .../Symbols/Source/SourceClassSymbol.cs | 3 +- .../Symbols/Source/SourceFieldSymbol.cs | 5 +- src/Draco.Compiler/Internal/Syntax/Parser.cs | 47 ++------------- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 59 ++----------------- 9 files changed, 34 insertions(+), 119 deletions(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index 2efacaec6..ff4b7b1f0 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -44,7 +44,7 @@ func main() { } class Foo { - field i: int; + field var i: int; func increment(this) { this.i += 1; } diff --git a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs index d090d3eb7..9aa93fe9b 100644 --- a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs +++ b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs @@ -89,7 +89,7 @@ func main() { this.T(TokenKind.Identifier); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -157,7 +157,7 @@ func main() { this.T(TokenKind.Identifier); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -186,7 +186,7 @@ func main() { this.T(TokenKind.Identifier); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -234,7 +234,7 @@ func foo() { } this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -1975,7 +1975,7 @@ func foo(@Attr2("this is a parameter") x: int32) {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "foo"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); { this.N(); { @@ -2038,7 +2038,7 @@ public func bar() {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "foo"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); { @@ -2051,7 +2051,7 @@ public func bar() {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "bar"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); { diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index 66423a738..ab4cd6ba5 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -167,37 +167,38 @@ public static FunctionDeclarationSyntax FunctionDeclaration( body); public static VariableDeclarationSyntax VariableDeclaration( - bool globql, + bool global, string name, - TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(null, globql, true, name, type, value); + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(null, global, false, true, name, type, value); public static VariableDeclarationSyntax VariableDeclaration( Visibility visibility, - bool globql, + bool global, string name, - TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), globql, true, name, type, value); + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), global, false, true, name, type, value); public static VariableDeclarationSyntax ImmutableVariableDeclaration( bool global, string name, - TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(null, global, false, name, type, value); + TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration(null, global, false, false, name, type, value); public static VariableDeclarationSyntax ImmutableVariableDeclaration( Visibility visibility, bool global, string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), global, false, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration(Visibility(visibility), global, false, false, name, type, value); public static VariableDeclarationSyntax VariableDeclaration( TokenKind? visibility, bool global, + bool field, bool isMutable, - string name, - TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration( + string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => VariableDeclaration( [], visibility, global ? TokenKind.KeywordGlobal : null, + field ? TokenKind.KeywordField : null, isMutable ? TokenKind.KeywordVar : TokenKind.KeywordVal, name, type is null ? null : TypeSpecifier(type), diff --git a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs index aac00d076..76ce7789c 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs @@ -134,7 +134,6 @@ or ForExpressionSyntax public static bool DefinesSymbol(SyntaxNode node) => node is FunctionDeclarationSyntax or VariableDeclarationSyntax - or FieldDeclarationSyntax or ParameterSyntax or LabelDeclarationSyntax or ClassDeclarationSyntax; diff --git a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs index 727dac9e4..8a3b5e38b 100644 --- a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs @@ -169,8 +169,9 @@ private void Build() { FunctionDeclarationSyntax function => new SourceFunctionSymbol(this.ContainingSymbol, function), ParameterSyntax parameter => new SourceParameterSymbol((FunctionSymbol)this.ContainingSymbol, parameter), - VariableDeclarationSyntax variable => new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable), - FieldDeclarationSyntax field => new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, field), + VariableDeclarationSyntax variable => variable.FieldKeyword != null ? + new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, variable) : + new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable), LabelDeclarationSyntax label => new SourceLabelSymbol(this.ContainingSymbol, label), _ => null, }; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index ac141bc12..2070b5a85 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -94,7 +94,8 @@ private Symbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declara { case FunctionDeclarationSyntax functionSyntax: return new SourceFunctionSymbol(this, functionSyntax); - case FieldDeclarationSyntax fieldSyntax: + case VariableDeclarationSyntax fieldSyntax: + if (fieldSyntax.FieldKeyword is null) throw new NotImplementedException(); return new SourceFieldSymbol(this, fieldSyntax); default: throw new NotImplementedException(); // TODO implement this diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs index 452adcf99..ea6bca472 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -4,7 +4,7 @@ using Draco.Compiler.Internal.Binding; namespace Draco.Compiler.Internal.Symbols.Source; -internal class SourceFieldSymbol(TypeSymbol containingSymbol, FieldDeclarationSyntax field) : FieldSymbol, ISourceSymbol +internal class SourceFieldSymbol(TypeSymbol containingSymbol, VariableDeclarationSyntax field) : FieldSymbol, ISourceSymbol { public override TypeSymbol ContainingSymbol => containingSymbol; @@ -19,9 +19,8 @@ private TypeSymbol BindTypeIfNeeded(IBinderProvider binder) => private TypeSymbol? type; public override bool IsMutable => this.DeclaringSyntax.Keyword.Kind == TokenKind.KeywordVar; - public override string Name => this.DeclaringSyntax.Name.Text; - public override FieldDeclarationSyntax DeclaringSyntax { get; } = field; + public override VariableDeclarationSyntax DeclaringSyntax { get; } = field; private TypeSymbol BindType(IBinderProvider binderProvider) { diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 4317b1e40..f5824b20d 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -382,10 +382,11 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordModule: return this.ParseModuleDeclaration(attributes, visibility, context); case TokenKind.KeywordField: - return this.ParseFieldDeclaration(attributes, visibility, global, context); + var fieldToken = this.Advance(); + return this.ParseVariableDeclaration(attributes, visibility, global, fieldToken, context); case TokenKind.KeywordVar: case TokenKind.KeywordVal: - return this.ParseVariableDeclaration(attributes, visibility, global, context); + return this.ParseVariableDeclaration(attributes, visibility, global, null, context); case TokenKind.Identifier when this.PeekKind(1) == TokenKind.Colon: return this.ParseLabelDeclaration(attributes, visibility, context); @@ -605,6 +606,7 @@ private VariableDeclarationSyntax ParseVariableDeclaration( SyntaxList? attributes, SyntaxToken? visibility, SyntaxToken? global, + SyntaxToken? field, DeclarationContext context) { if (context == DeclarationContext.Local && attributes is not null) @@ -634,49 +636,10 @@ private VariableDeclarationSyntax ParseVariableDeclaration( } // Eat semicolon at the end of declaration var semicolon = this.Expect(TokenKind.Semicolon); - return new VariableDeclarationSyntax(attributes, visibility, global, keyword, identifier, type, assignment, semicolon); + return new VariableDeclarationSyntax(attributes, visibility, global, field, keyword, identifier, type, assignment, semicolon); } - /// - /// Parses a . - /// - /// The attributes on the field. - /// The visibility modifier on the field. - /// The current declaration context. - /// The parsed . - private FieldDeclarationSyntax ParseFieldDeclaration( - SyntaxList? attributes, - SyntaxToken? visibility, - SyntaxToken? global, - DeclarationContext context) - { - // NOTE: We will always call this function by checking the leading keyword - var keyword = this.Advance(); - var identifier = this.Expect(TokenKind.Identifier); - // We don't necessarily have type specifier - TypeSpecifierSyntax? type = null; - if (this.PeekKind() == TokenKind.Colon) type = this.ParseTypeSpecifier(); - // We don't necessarily have value assigned to the variable - ValueSpecifierSyntax? assignment = null; - if (this.Matches(TokenKind.Assign, out var assign)) - { - var value = this.ParseExpression(); - assignment = new(assign, value); - } - - // Eat semicolon at the end of declaration - var semicolon = this.Expect(TokenKind.Semicolon); - - var syntax = new FieldDeclarationSyntax(attributes, visibility, keyword, identifier, type, assignment, semicolon); - if (context == DeclarationContext.Local) - { - var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedFieldDeclarationInFunction); - this.AddDiagnostic(syntax, info); - } - return syntax; - } - /// /// Parses a function declaration. /// diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 7b6b73c58..df71aa130 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -692,6 +692,11 @@ + + The optional field keyword that mark this variable as field. + + + The keyword introducing the variable, either 'var' or 'val'. @@ -726,60 +731,6 @@ - - - A field declaration. - - - - - The attributes of this field. - - - - - - - The visibility modifier keyword possibly starting the declaration. - - - - - - - - - The keyword introducing the field: 'field'. - - - - - - - The name of the declared variable. - - - - - - - The type of the declared variable. - - - - - The initializer value for the variable. - - - - - The semicolon closing the variable declaration. - - - - - - A type specifier referencing a type. From c7673ef8f8f16341b274993e64fec3b7cc1bb5cb Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 9 Oct 2024 21:31:38 +0200 Subject: [PATCH 022/109] wip --- src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs | 2 +- src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index ff4b7b1f0..784489eaa 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -44,7 +44,7 @@ func main() { } class Foo { - field var i: int; + field var i: int32; func increment(this) { this.i += 1; } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs index ea6bca472..0cb05d2c6 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFieldSymbol.cs @@ -22,6 +22,8 @@ private TypeSymbol BindTypeIfNeeded(IBinderProvider binder) => public override VariableDeclarationSyntax DeclaringSyntax { get; } = field; + public override string Name => this.DeclaringSyntax.Name.Text; + private TypeSymbol BindType(IBinderProvider binderProvider) { if (this.DeclaringSyntax.Type is null) throw new NotImplementedException(); // TODO: what should I do when the type is missing? Do we allow inference here ? From da57abc5dc63feebf591515958d411e572702c83 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 14 Oct 2024 02:32:26 +0200 Subject: [PATCH 023/109] wip --- .../Internal/Codegen/MetadataCodegen.cs | 1 + .../Metadata/MetadataNamespaceSymbol.cs | 2 +- .../Metadata/MetadataStaticClassSymbol.cs | 2 +- .../Symbols/Metadata/MetadataSymbol.cs | 14 ----------- .../Symbols/Metadata/MetadataTypeSymbol.cs | 2 +- .../Symbols/Source/SourceClassSymbol.cs | 8 +++++-- .../Symbols/Source/SourceModuleSymbol.cs | 8 ++++++- src/Draco.Compiler/Internal/Symbols/Symbol.cs | 14 +++++++++++ .../Synthetized/ConstructorFunctionSymbol.cs | 2 ++ .../Synthetized/DefaultConstructorSymbol.cs | 24 +++++++++++++++++++ 10 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 93b23103d..078be7a54 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -217,6 +217,7 @@ public EntityHandle GetEntityHandle(Symbol symbol) case TypeSymbol typeSymbol: { + // TODO: this branch of code currently cannot work. var blob = this.EncodeBlob(e => { var encoder = e.TypeSpecificationSignature(); diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs index bbbfcb926..aa23c7ce0 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs @@ -56,7 +56,7 @@ private ImmutableArray BuildMembers() var symbol = MetadataSymbol.ToSymbol(this, typeDef); result.Add(symbol); // Add additional symbols - result.AddRange(MetadataSymbol.GetAdditionalSymbols(symbol)); + result.AddRange(GetAdditionalSymbols(symbol)); } // Done diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs index ec507167c..c7af3b43b 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs @@ -66,7 +66,7 @@ private ImmutableArray BuildMembers() var symbol = MetadataSymbol.ToSymbol(this, typeDef); result.Add(symbol); // Add additional symbols - result.AddRange(MetadataSymbol.GetAdditionalSymbols(symbol)); + result.AddRange(GetAdditionalSymbols(symbol)); } // Methods diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs index e03a2ba13..7e0ca4a1b 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs @@ -39,20 +39,6 @@ public static Symbol ToSymbol(Symbol containingSymbol, TypeDefinition typeDefini } } - // TODO: This isn't dependent on metadata types anymore, we could move it out - /// - /// Retrieves additional symbols for the given . - /// - /// The symbol to get additional symbols for. - /// The additional symbols for the given . - public static IEnumerable GetAdditionalSymbols(Symbol symbol) - { - if (symbol is not TypeSymbol typeSymbol) return []; - if (typeSymbol.IsAbstract) return []; - // For other types we provide constructor functions - return typeSymbol.Constructors.Select(ctor => new ConstructorFunctionSymbol(ctor)); - } - /// /// Decodes the given constant. /// diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs index 018fca864..ee70792b1 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs @@ -153,7 +153,7 @@ private ImmutableArray BuildMembers() var symbol = MetadataSymbol.ToSymbol(this, typeDef); result.Add(symbol); // Add additional symbols - result.AddRange(MetadataSymbol.GetAdditionalSymbols(symbol)); + result.AddRange(GetAdditionalSymbols(symbol)); } // Methods diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 2070b5a85..6951e4664 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -9,6 +9,7 @@ using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; using Draco.Compiler.Internal.Declarations; +using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.Symbols.Source; @@ -38,6 +39,7 @@ public void Bind(IBinderProvider binderProvider) { this.BindGenericParametersIfNeeded(binderProvider); this.BindMembersIfNeeded(binderProvider); + } private ImmutableArray BindGenericParametersIfNeeded(IBinderProvider binderProvider) => @@ -74,12 +76,14 @@ private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvide private ImmutableArray BindMembers(IBinderProvider binder) { - if (this.DeclaringSyntax.Body is EmptyClassBodySyntax) return []; + + if (this.DeclaringSyntax.Body is EmptyClassBodySyntax) return [new DefaultConstructorSymbol(this)]; var bodyClass = this.DeclaringSyntax.Body as BlockClassBodySyntax; Debug.Assert(bodyClass is not null); var declarationsSyntaxes = bodyClass.Declarations.ToList(); - var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count); + var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count + 1); + members.Add(new DefaultConstructorSymbol(this)); foreach (var declarationSyntax in declarationsSyntaxes) { var member = this.BindDeclaration(binder, declarationSyntax); diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs index f76450e23..1030eebba 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs @@ -77,7 +77,13 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); result.Add(member); - // We chech for illegal shadowing + if (member is TypeSymbol typeSymbol) + { + result.AddRange(GetAdditionalSymbols(typeSymbol)); + } + + + // We check for illegal shadowing if (earlierMember is null) continue; // Overloading is legal diff --git a/src/Draco.Compiler/Internal/Symbols/Symbol.cs b/src/Draco.Compiler/Internal/Symbols/Symbol.cs index ecb1cafcb..c9fd88c78 100644 --- a/src/Draco.Compiler/Internal/Symbols/Symbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Symbol.cs @@ -8,6 +8,7 @@ using Draco.Compiler.Internal.Documentation; using Draco.Compiler.Internal.Symbols.Generic; using Draco.Compiler.Internal.Symbols.Metadata; +using Draco.Compiler.Internal.Symbols.Synthetized; using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.Symbols; @@ -329,4 +330,17 @@ private protected string GenericsToString() TokenKind.KeywordPublic => Api.Semantics.Visibility.Public, _ => throw new InvalidOperationException($"illegal visibility modifier token {kind}"), }; + + /// + /// Retrieves additional symbols for the given . + /// + /// The symbol to get additional symbols for. + /// The additional symbols for the given . + public static IEnumerable GetAdditionalSymbols(Symbol symbol) + { + if (symbol is not TypeSymbol typeSymbol) return []; + if (typeSymbol.IsAbstract) return []; + // For other types we provide constructor functions + return typeSymbol.Constructors.Select(ctor => new ConstructorFunctionSymbol(ctor)); + } } diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs index a2323060b..80fdca609 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs @@ -19,6 +19,8 @@ internal sealed class ConstructorFunctionSymbol(FunctionSymbol ctorDefinition) : public override SymbolDocumentation Documentation => ctorDefinition.Documentation; internal override string RawDocumentation => ctorDefinition.RawDocumentation; + public override Symbol? ContainingSymbol { get; } = ctorDefinition; + public override ImmutableArray GenericParameters => InterlockedUtils.InitializeDefault(ref this.genericParameters, this.BuildGenericParameters); private ImmutableArray genericParameters; diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs new file mode 100644 index 000000000..77cc3d805 --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Draco.Compiler.Internal.Symbols.Synthetized; + +internal sealed class DefaultConstructorSymbol(TypeSymbol containingSymbol) : FunctionSymbol +{ + + public override ImmutableArray Parameters => []; + + public override TypeSymbol ReturnType { get; } = WellKnownTypes.Unit; + + public override bool IsConstructor => true; + + public override string Name => "Foo"; + + public override Symbol? ContainingSymbol { get; } = containingSymbol; + + public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; +} From 2d3aaa929060f710563acbae0bd1a9f447cf6f6a Mon Sep 17 00:00:00 2001 From: Kuinox Date: Tue, 15 Oct 2024 00:30:35 +0200 Subject: [PATCH 024/109] Fixed MetadataCodegen --- .../Internal/Codegen/MetadataCodegen.cs | 12 +++++++++++- .../Internal/Symbols/Source/SourceClassSymbol.cs | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 078be7a54..74a8d33b8 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -217,7 +217,6 @@ public EntityHandle GetEntityHandle(Symbol symbol) case TypeSymbol typeSymbol: { - // TODO: this branch of code currently cannot work. var blob = this.EncodeBlob(e => { var encoder = e.TypeSpecificationSignature(); @@ -895,6 +894,17 @@ public void EncodeSignatureType(SignatureTypeEncoder encoder, TypeSymbol type) return; } + if (type is SourceClassSymbol sourceClass) + { + encoder.Type( + type: this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName), + isValueType: sourceClass.IsValueType); + return; + } + // TODO throw new NotImplementedException(); } diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 6951e4664..5d8303014 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -30,7 +30,7 @@ public SourceClassSymbol(Symbol containingSymbol, ClassDeclaration declaration) { } - public override Symbol? ContainingSymbol { get; } = containingSymbol; + public override Symbol ContainingSymbol { get; } = containingSymbol; public override string Name => this.DeclaringSyntax.Name.Text; public override ClassDeclarationSyntax DeclaringSyntax => syntax; From 712558bb20359f8599a693c8167d0d91cd70a2e5 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Tue, 15 Oct 2024 01:03:07 +0200 Subject: [PATCH 025/109] Fix some codegen --- .../EndToEnd/CodeExecutionTests.cs | 12 +++++++++++- src/Draco.Compiler/Internal/Codegen/CilCodegen.cs | 9 +++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index 784489eaa..1d5072159 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -41,15 +41,25 @@ public void InstanceField() func main() { var foo = Foo(); + foo.increment(); + foo.display(); } class Foo { field var i: int32; - func increment(this) { + public func increment(this) { this.i += 1; } + + public func display(this) { + WriteLine(this.i); + } } """); + + var stringWriter = new StringWriter(); + _ = Invoke(assembly: assembly, stdout: stringWriter); + } } diff --git a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs index d7a399315..1e6bdba2c 100644 --- a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs @@ -227,6 +227,10 @@ IEnumerable RemainingOperands() this.EncodeToken(global); break; } + case FieldSymbol field: + this.InstructionEncoder.OpCode(ILOpCode.Ldfld); + this.EncodeToken(field); + break; default: throw new InvalidOperationException(); } @@ -282,6 +286,11 @@ IEnumerable RemainingOperands() this.InstructionEncoder.OpCode(ILOpCode.Stsfld); this.EncodeToken(global); break; + case FieldSymbol field: + this.EncodePush(NextOperand()); + this.InstructionEncoder.OpCode(ILOpCode.Stfld); + this.EncodeToken(field); + break; default: throw new InvalidOperationException(); } From 568c52723364e4a3adf8bfc3ab222b785aadc9aa Mon Sep 17 00:00:00 2001 From: Kuinox Date: Fri, 18 Oct 2024 01:23:23 +0200 Subject: [PATCH 026/109] some progress. --- src/Draco.Compiler.Tests/TestUtilities.cs | 1 + .../Internal/Binding/Binder_Expression.cs | 15 ++++++++++++--- .../Internal/Binding/SymbolResolutionErrors.cs | 6 ++++++ .../Internal/BoundTree/BoundNodes.xml | 4 ---- .../Internal/OptimizingIr/Model/Procedure.cs | 6 +++++- .../Symbols/Source/SourceThisParameterSymbol.cs | 4 +++- .../Symbols/Syntax/SyntaxFunctionSymbol.cs | 11 +++++++++++ 7 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/Draco.Compiler.Tests/TestUtilities.cs b/src/Draco.Compiler.Tests/TestUtilities.cs index 2ccc571f8..3c52798ec 100644 --- a/src/Draco.Compiler.Tests/TestUtilities.cs +++ b/src/Draco.Compiler.Tests/TestUtilities.cs @@ -182,6 +182,7 @@ private static Assembly CompileToAssemblyImpl( }; var peStream = CompileToMemory(compilation); + File.WriteAllBytes("output.dll", peStream.ToArray()); var assembly = assemblyLoadContext.LoadFromStream(peStream); // Load additional references diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index fe86c2ebc..1b9eb0567 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -12,6 +12,8 @@ using Draco.Compiler.Internal.Solver.Tasks; using Draco.Compiler.Internal.Symbols; using Draco.Compiler.Internal.Symbols.Error; +using Draco.Compiler.Internal.Symbols.Source; +using Draco.Compiler.Internal.Symbols.Syntax; using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.Binding; @@ -679,11 +681,18 @@ private async BindingTask BindIndexExpression(IndexExpressionSy } } - private BindingTask BindThisExpression(ThisExpressionSyntax @this, ConstraintSolver constraints, DiagnosticBag diagnostics) + private BindingTask BindThisExpression(ThisExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { - var declaringType = this.LookupDeclaringType(@this, diagnostics); + var thisArg = ((SyntaxFunctionSymbol)this.ContainingSymbol!).ThisArgument; + if (thisArg == null) + { + diagnostics.Add(Diagnostic.Create( + template: SymbolResolutionErrors.NoThisInStaticMethod, + location: syntax.Location, + formatArgs: [this.ContainingSymbol!.Name])); - var boundThis = new BoundThisExpression(@this, declaringType); + } + var boundThis = new BoundParameterExpression(syntax, thisArg); // todo: what should i do here ? return BindingTask.FromResult(boundThis); } diff --git a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs index 0be99499c..e4c5e9d2c 100644 --- a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs +++ b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs @@ -194,4 +194,10 @@ internal static class SymbolResolutionErrors severity: DiagnosticSeverity.Error, format: "there is no type instance to reference.", code: Code(21)); + + public static readonly DiagnosticTemplate NoThisInStaticMethod = DiagnosticTemplate.Create( + title: "instance reference in static method", + severity: DiagnosticSeverity.Error, + format: "cannot reference the type instance in static method {0}", + code: Code(22)); } diff --git a/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml b/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml index 4ec161676..c0fca7351 100644 --- a/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml +++ b/src/Draco.Compiler/Internal/BoundTree/BoundNodes.xml @@ -191,10 +191,6 @@ - - - - diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index 0ce3ecc8f..74b93f816 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using Draco.Compiler.Internal.Symbols; +using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.OptimizingIr.Model; @@ -47,9 +48,12 @@ public Procedure(Module declaringModule, Type? declaringType, FunctionSymbol sym public int GetParameterIndex(ParameterSymbol symbol) { + if (symbol is SourceThisParameterSymbol) return 0; + var isStaticMethod = symbol.ContainingSymbol.IsStatic; var idx = this.Symbol.Parameters.IndexOf(symbol); if (idx == -1) throw new System.ArgumentOutOfRangeException(nameof(symbol)); - return idx; + return isStaticMethod ? idx : idx + 1; + } public BasicBlock DefineBasicBlock(LabelSymbol symbol) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs index 31af4fec1..6c090745b 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs @@ -5,7 +5,7 @@ namespace Draco.Compiler.Internal.Symbols.Source; -internal sealed class SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterSyntax syntax) : ParameterSymbol +internal sealed class SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterSyntax syntax) : ParameterSymbol, ISourceSymbol { public override string Name => "this"; public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; @@ -14,4 +14,6 @@ internal sealed class SourceThisParameterSymbol(FunctionSymbol containingSymbol, public override ImmutableArray Attributes => []; public override TypeSymbol Type { get; } = (containingSymbol.ContainingSymbol as TypeSymbol)!; + + public void Bind(IBinderProvider binderProvider) { } } diff --git a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs index cdb7009d1..6f8769b98 100644 --- a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs @@ -35,6 +35,16 @@ internal abstract class SyntaxFunctionSymbol( public override ImmutableArray Parameters => this.BindParametersIfNeeded(this.DeclaringCompilation!); private ImmutableArray parameters; + public SourceThisParameterSymbol? ThisArgument + { + get + { + this.BindParametersIfNeeded(this.DeclaringCompilation!); + return this.thisArgument; + } + } + private SourceThisParameterSymbol? thisArgument; + public override TypeSymbol ReturnType => this.BindReturnTypeIfNeeded(this.DeclaringCompilation!); private TypeSymbol? returnType; @@ -110,6 +120,7 @@ private ImmutableArray BindParameters(IBinderProvider binderPro var asSymbol = new SourceThisParameterSymbol(this, thisParameter); if (i == 0) { + this.thisArgument = asSymbol; isInstance = asSymbol; continue; } From d798797f8ade95dc3162e86143392a0436716a10 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Fri, 18 Oct 2024 01:47:02 +0200 Subject: [PATCH 027/109] wip --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 7 +++++++ .../Internal/OptimizingIr/Codegen/ModuleCodegen.cs | 6 ++++++ .../Internal/OptimizingIr/Model/Module.cs | 10 ++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 74a8d33b8..63362b8fa 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -467,6 +467,12 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = n currentFieldIndex++; } + foreach (var type in module.Types.Values) + { + //TODO: what to do about the parent here ? + this.EncodeClass(type, parent: null, ref fieldIndex, ref procIndex); + } + // Go through procedures foreach (var procedure in module.Procedures.Values) { @@ -507,6 +513,7 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = n fieldList: MetadataTokens.FieldDefinitionHandle(fieldIndex), methodList: MetadataTokens.MethodDefinitionHandle(procIndex)); + // If this isn't top level module, we specify nested relationship if (parentModule is not null) this.MetadataBuilder.AddNestedType(createdModule, parentModule.Value); diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs index 73fea6976..e62ff5bb2 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs @@ -67,6 +67,12 @@ public override void VisitGlobal(GlobalSymbol globalSymbol) } } + public override void VisitType(TypeSymbol typeSymbol) + { + var type = this.module.DefineType(typeSymbol); + base.VisitType(typeSymbol); + } + public override void VisitFunction(FunctionSymbol functionSymbol) { if (functionSymbol.Body is null) return; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index ec5fc2861..c45976c1e 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -84,6 +84,16 @@ public Module DefineModule(ModuleSymbol moduleSymbol) return (Module)result; } + public Type DefineType(TypeSymbol typeSymbol) + { + if (!this.types.TryGetValue(typeSymbol, out var result)) + { + result = new Type(this, typeSymbol); + this.types.Add(typeSymbol, result); + } + return (Type)result; + } + public override string ToString() { var result = new StringBuilder(); From 5f2230092c55b3a43c93f5decb9698d75a2acac3 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 20 Oct 2024 03:05:43 +0200 Subject: [PATCH 028/109] wip --- .../OptimizingIr/Codegen/ClassCodegen.cs | 56 +++++++++++++++++++ .../OptimizingIr/Codegen/LocalCodegen.cs | 8 ++- .../OptimizingIr/Codegen/ModuleCodegen.cs | 5 +- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs new file mode 100644 index 000000000..d8aa0e633 --- /dev/null +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Draco.Compiler.Api; +using Draco.Compiler.Internal.BoundTree; +using Draco.Compiler.Internal.Lowering; +using Draco.Compiler.Internal.OptimizingIr.Model; +using Draco.Compiler.Internal.Symbols; + +namespace Draco.Compiler.Internal.OptimizingIr.Codegen; + + +/// +/// Generates IR code for a class. +/// +internal sealed class ClassCodegen(ModuleCodegen moduleCodegen, Type @class) : SymbolVisitor +{ + private Compilation Compilation => moduleCodegen.Compilation; + private bool EmitSequencePoints => moduleCodegen.EmitSequencePoints; + + // TODO: Copypasta from ModuleCodegen + public override void VisitFunction(FunctionSymbol functionSymbol) + { + if (functionSymbol.Body is null) return; + + // Add procedure + var procedure = @class.DefineMethod(functionSymbol); + + // Create the body + var body = this.RewriteBody(functionSymbol.Body); + // Yank out potential local functions and closures + var (bodyWithoutLocalFunctions, localFunctions) = ClosureRewriter.Rewrite(body); + // Compile it + var bodyCodegen = new LocalCodegen(this.Compilation, procedure); + bodyWithoutLocalFunctions.Accept(bodyCodegen); + + // Compile the local functions + foreach (var localFunc in localFunctions) this.VisitFunction(localFunc); + } + + public override void VisitField(FieldSymbol fieldSymbol) + { + // No-op, the Class model reads it up from the symbol + } + + // TODO: Copypasta from ModuleCodegen + // TODO: Except we check for syntax not being null because we can have synthetized symbols + private BoundNode RewriteBody(BoundNode body) + { + // If needed, inject sequence points + if (body.Syntax is not null && this.EmitSequencePoints) body = SequencePointInjector.Inject(body); + // Desugar it + return body.Accept(new LocalRewriter(this.Compilation)); + } +} diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs index 045217814..4fe21d861 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using Draco.Compiler.Api; using Draco.Compiler.Internal.Binding; @@ -36,7 +37,12 @@ public LocalCodegen(Compilation compilation, Procedure procedure) } private void Compile(BoundStatement stmt) => stmt.Accept(this); - private IOperand Compile(BoundExpression expr) => expr.Accept(this); + private IOperand Compile(BoundExpression expr) + { + var val = expr.Accept(this); + Debug.Assert(val != null); + return val; + } private void AttachBlock(BasicBlock basicBlock) { diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs index e62ff5bb2..4002a7599 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs @@ -69,8 +69,11 @@ public override void VisitGlobal(GlobalSymbol globalSymbol) public override void VisitType(TypeSymbol typeSymbol) { + if (typeSymbol is not SourceClassSymbol sourceClass) return; + var type = this.module.DefineType(typeSymbol); - base.VisitType(typeSymbol); + var typeCodegen = new ClassCodegen(this, type); + sourceClass.Accept(typeCodegen); } public override void VisitFunction(FunctionSymbol functionSymbol) From abd2580a82311e5cd5d8be52090a307dd063d237 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 21 Oct 2024 02:02:01 +0200 Subject: [PATCH 029/109] wip --- .../Internal/Codegen/MetadataCodegen.cs | 61 +++++++++++-------- .../Symbols/Source/SourceFunctionSymbol.cs | 2 + 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 63362b8fa..26ee1daad 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -456,21 +456,27 @@ private void EncodeAssembly() } } - private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = null, int fieldIndex = 1, int procIndex = 1) + private void EncodeModule(IModule module) { - var currentFieldIndex = fieldIndex; - var currentProcIndex = procIndex; + var fieldIndex = 1; + var procIndex = 1; + this.EncodeModule(module, parent: null, fieldIndex: ref fieldIndex, procIndex: ref procIndex); + } + + private void EncodeModule( + IModule module, + TypeDefinitionHandle? parent, + ref int fieldIndex, + ref int procIndex) + { + var startFieldIndex = fieldIndex; + var startProcIndex = procIndex; + // Go through globals foreach (var global in module.Globals) { this.EncodeGlobal(global); - currentFieldIndex++; - } - - foreach (var type in module.Types.Values) - { - //TODO: what to do about the parent here ? - this.EncodeClass(type, parent: null, ref fieldIndex, ref procIndex); + ++fieldIndex; } // Go through procedures @@ -484,22 +490,17 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = n // If this is the entry point, save it if (ReferenceEquals(this.assembly.EntryPoint, procedure)) this.EntryPointHandle = handle; - currentProcIndex++; + + ++procIndex; } // Compile global initializer too this.EncodeProcedure(module.GlobalInitializer, specialName: ".cctor"); - currentProcIndex++; + ++procIndex; - TypeAttributes visibility; - if (module.Symbol.Visibility == Api.Semantics.Visibility.Public) - { - visibility = parentModule is not null ? TypeAttributes.NestedPublic : TypeAttributes.Public; - } - else - { - visibility = parentModule is not null ? TypeAttributes.NestedAssembly : TypeAttributes.NotPublic; - } + var visibility = module.Symbol.Visibility == Api.Semantics.Visibility.Public + ? (parent is not null ? TypeAttributes.NestedPublic : TypeAttributes.Public) + : (parent is not null ? TypeAttributes.NestedAssembly : TypeAttributes.NotPublic); var attributes = visibility | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Abstract | TypeAttributes.Sealed; var name = string.IsNullOrEmpty(module.Name) ? CompilerConstants.DefaultModuleName : module.Name; @@ -510,17 +511,22 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parentModule = n @namespace: default, name: name, baseType: this.systemObjectReference, - fieldList: MetadataTokens.FieldDefinitionHandle(fieldIndex), - methodList: MetadataTokens.MethodDefinitionHandle(procIndex)); - + fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), + methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex)); // If this isn't top level module, we specify nested relationship - if (parentModule is not null) this.MetadataBuilder.AddNestedType(createdModule, parentModule.Value); + if (parent is not null) this.MetadataBuilder.AddNestedType(createdModule, parent.Value); + + // We encode every class + foreach (var @class in module.Types.Values) + { + this.EncodeClass(@class, parent: createdModule, fieldIndex: ref fieldIndex, procIndex: ref procIndex); + } // We encode every submodule foreach (var subModule in module.Submodules.Values) { - this.EncodeModule(subModule, createdModule, currentFieldIndex, currentProcIndex); + this.EncodeModule(subModule, parent: createdModule, fieldIndex: ref fieldIndex, procIndex: ref procIndex); } } @@ -573,10 +579,11 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure, string? spe hasDynamicStackAllocation: false); // Determine attributes - var attributes = MethodAttributes.Static | MethodAttributes.HideBySig; + var attributes = MethodAttributes.HideBySig; attributes |= specialName is null ? visibility : MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; + if (procedure.Symbol.IsStatic) attributes |= MethodAttributes.Static; // Parameters var parameterList = this.NextParameterHandle; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs index 4e14e1acb..16dd04345 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs @@ -27,6 +27,8 @@ public SourceFunctionSymbol(Symbol containingSymbol, FunctionDeclaration declara { } + public override bool IsStatic => this.ThisArgument == null; + public override void Bind(IBinderProvider binderProvider) { this.BindAttributesIfNeeded(binderProvider); From c25ca7fb5c9d7e30b3e94c12876ad0099e5266f4 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 23 Oct 2024 01:20:54 +0200 Subject: [PATCH 030/109] Make constructor generate (but incorrectly) --- src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs | 1 + .../Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index 47090c251..4fecc512e 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -131,6 +131,7 @@ public delegate IOperand CodegenDelegate( /// /// The bound body of this function, if it has one. /// This is the case for in-source and certain synthesized functions. + /// When null, the function will not be emitted. /// public virtual BoundStatement? Body => null; diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs index 77cc3d805..1f28ed3b0 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs @@ -4,6 +4,10 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.BoundTree; +using static Draco.Compiler.Internal.BoundTree.BoundTreeFactory; + namespace Draco.Compiler.Internal.Symbols.Synthetized; @@ -21,4 +25,5 @@ internal sealed class DefaultConstructorSymbol(TypeSymbol containingSymbol) : Fu public override Symbol? ContainingSymbol { get; } = containingSymbol; public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; + public override BoundStatement? Body { get; } = ExpressionStatement(null, ReturnExpression(null, BoundUnitExpression.Default)); } From 71f8162e89b02858a08d443cfecd03e43550bd1f Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 23 Oct 2024 21:04:00 +0200 Subject: [PATCH 031/109] constructor have a special name. --- .../Internal/Codegen/MetadataCodegen.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 26ee1daad..c3d7035fe 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -15,6 +15,7 @@ using Draco.Compiler.Internal.Symbols.Metadata; using Draco.Compiler.Internal.Symbols.Script; using Draco.Compiler.Internal.Symbols.Source; +using Draco.Compiler.Internal.Symbols.Synthetized; using Draco.Compiler.Internal.Symbols.Synthetized.Array; namespace Draco.Compiler.Internal.Codegen; @@ -702,7 +703,15 @@ ref int procIndex // Procedures foreach (var proc in type.Methods.Values) { - var handle = this.EncodeProcedure(proc); + if (proc.Symbol is DefaultConstructorSymbol ctor) + { + var handle = this.EncodeProcedure(proc, ".ctor"); + } + else + { + var handle = this.EncodeProcedure(proc); + + } ++procIndex; // Todo: properties From 67b98dc0611af7bce604501371d2426270c0acaf Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 24 Oct 2024 00:22:48 +0200 Subject: [PATCH 032/109] it work. --- .../Internal/Codegen/MetadataCodegen.cs | 10 ++++------ .../Internal/OptimizingIr/Model/IProcedure.cs | 5 +++++ .../Internal/OptimizingIr/Model/IType.cs | 2 +- .../Internal/OptimizingIr/Model/Procedure.cs | 2 ++ .../Internal/OptimizingIr/Model/Type.cs | 18 ++++++------------ .../Synthetized/DefaultConstructorSymbol.cs | 4 +++- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index c3d7035fe..36f86ec51 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -580,11 +580,9 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure, string? spe hasDynamicStackAllocation: false); // Determine attributes - var attributes = MethodAttributes.HideBySig; - attributes |= specialName is null - ? visibility - : MethodAttributes.Private | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; + var attributes = MethodAttributes.HideBySig | visibility; if (procedure.Symbol.IsStatic) attributes |= MethodAttributes.Static; + if (procedure.Symbol.IsSpecialName) attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; // Parameters var parameterList = this.NextParameterHandle; @@ -634,7 +632,7 @@ private BlobHandle EncodeGlobalSignature(GlobalSymbol global) => private BlobHandle EncodeProcedureSignature(IProcedure procedure) => this.EncodeBlob(e => { e - .MethodSignature(genericParameterCount: procedure.Generics.Count) + .MethodSignature(genericParameterCount: procedure.Generics.Count, isInstanceMethod: !procedure.IsStatic) .Parameters(procedure.Parameters.Count, out var retEncoder, out var paramsEncoder); this.EncodeReturnType(retEncoder, procedure.ReturnType); foreach (var param in procedure.Parameters) @@ -720,7 +718,7 @@ ref int procIndex // Fields foreach (var field in type.Fields) { - this.EncodeField(field.Key); + this.EncodeField(field); ++fieldIndex; } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs index 2740da8af..02ae2ca94 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs @@ -13,6 +13,11 @@ internal interface IProcedure /// public FunctionSymbol Symbol { get; } + /// + /// Whether this procedure is static or not. + /// + public bool IsStatic { get; } + /// /// The name of this procedure. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs index b51770cd8..668ceb855 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs @@ -38,5 +38,5 @@ internal interface IType /// /// The fields on this type. /// - public IReadOnlyDictionary Fields { get; } + public IReadOnlyList Fields { get; } } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index 74b93f816..bcfd843ca 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -34,6 +34,8 @@ internal sealed class Procedure : IProcedure public IReadOnlyList Locals => this.locals; public IReadOnlyList Registers => this.registers; + public bool IsStatic => this.Symbol.IsStatic; + private readonly Dictionary basicBlocks = []; private readonly List locals = []; private readonly List registers = []; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs index 1391dd68a..ac39a13a7 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; using Draco.Compiler.Internal.Symbols; namespace Draco.Compiler.Internal.OptimizingIr.Model; @@ -15,10 +17,12 @@ internal class Type(Module declaringModule, TypeSymbol symbol) : IType public IReadOnlyList Generics => this.Symbol.GenericParameters; public IReadOnlyDictionary Methods => this.methods; - public IReadOnlyDictionary Fields => this.fields; + public IReadOnlyList Fields => InterlockedUtils.InitializeDefault( + ref this.fields, + () => this.Symbol.DefinedMembers.OfType().ToImmutableArray()); + private ImmutableArray fields; private readonly Dictionary methods = []; - private readonly Dictionary fields = []; public Procedure DefineMethod(FunctionSymbol functionSymbol) { @@ -29,14 +33,4 @@ public Procedure DefineMethod(FunctionSymbol functionSymbol) } return (Procedure)result; } - - public Field DefineField(FieldSymbol fieldSymbol) - { - if (!this.fields.TryGetValue(fieldSymbol, out var result)) - { - result = new Field(fieldSymbol, this); - this.fields.Add(fieldSymbol, result); - } - return (Field)result; - } } diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs index 1f28ed3b0..17f6ef483 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -19,8 +20,9 @@ internal sealed class DefaultConstructorSymbol(TypeSymbol containingSymbol) : Fu public override TypeSymbol ReturnType { get; } = WellKnownTypes.Unit; public override bool IsConstructor => true; + public override bool IsStatic => false; - public override string Name => "Foo"; + public override string Name => ".ctor"; public override Symbol? ContainingSymbol { get; } = containingSymbol; From f4f5e0f6cd6cb488ca3a9d57b31a481edccb33f7 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 24 Oct 2024 00:37:49 +0200 Subject: [PATCH 033/109] ok there is a few bugs remaining --- src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs index 4fe21d861..3c44356eb 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs @@ -40,7 +40,6 @@ public LocalCodegen(Compilation compilation, Procedure procedure) private IOperand Compile(BoundExpression expr) { var val = expr.Accept(this); - Debug.Assert(val != null); return val; } From a6d119d0451b6ae415f6dd40a1c8f2f2a9102d89 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 24 Oct 2024 10:24:26 +0200 Subject: [PATCH 034/109] tests cleanup. --- .../EndToEnd/CodeExecutionTests.cs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs index 1d5072159..85fcfcf13 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs @@ -16,10 +16,6 @@ public void ClassHelloWorld() var assembly = CompileToAssembly(""" import System.Console; - func main() { - WriteLine("Hello, World!"); - } - class Foo { func bar() { WriteLine("Hello, World!"); @@ -28,7 +24,7 @@ func bar() { """); var stringWriter = new StringWriter(); - _ = Invoke(assembly: assembly, stdout: stringWriter); + _ = Invoke(assembly: assembly, stdout: stringWriter, methodName: "bar", moduleName: "FreeFunctions.Foo"); Assert.Equal($"Hello, World!{Environment.NewLine}", stringWriter.ToString(), ignoreLineEndingDifferences: true); } @@ -39,10 +35,10 @@ public void InstanceField() var assembly = CompileToAssembly(""" import System.Console; - func main() { + func main(): int32 { var foo = Foo(); foo.increment(); - foo.display(); + return foo.get(); } class Foo { @@ -51,15 +47,16 @@ public func increment(this) { this.i += 1; } - public func display(this) { - WriteLine(this.i); + public func get(this): int32 { + return this.i; } } """); var stringWriter = new StringWriter(); - _ = Invoke(assembly: assembly, stdout: stringWriter); + var value = Invoke(assembly: assembly, stdout: stringWriter); + Assert.Equal(1, value); } } From 2c93d54b5cdeac4da214e3c7c69768fe9d9dd869 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Thu, 24 Oct 2024 10:25:56 +0200 Subject: [PATCH 035/109] remove debug dll dump --- src/Draco.Compiler.Tests/TestUtilities.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Draco.Compiler.Tests/TestUtilities.cs b/src/Draco.Compiler.Tests/TestUtilities.cs index 3c52798ec..2ccc571f8 100644 --- a/src/Draco.Compiler.Tests/TestUtilities.cs +++ b/src/Draco.Compiler.Tests/TestUtilities.cs @@ -182,7 +182,6 @@ private static Assembly CompileToAssemblyImpl( }; var peStream = CompileToMemory(compilation); - File.WriteAllBytes("output.dll", peStream.ToArray()); var assembly = assemblyLoadContext.LoadFromStream(peStream); // Load additional references From a2a35db116faca3d365127cca4e4f19198e14bb0 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sat, 26 Oct 2024 18:11:48 +0200 Subject: [PATCH 036/109] wip fixing tests. --- .../Semantics/ControlFlowGraphTests.cs | 4 +-- .../Semantics/DefiniteAssignmentTests.cs | 30 +++++++++---------- .../Semantics/SemanticModelTests.cs | 2 +- .../Semantics/SingleAssignmentTests.cs | 12 ++++---- .../Semantics/SymbolResolutionTests.cs | 1 + .../Semantics/TypeCheckingTests.cs | 1 + .../Syntax/ParserTests.cs | 4 +-- .../Internal/Codegen/MetadataCodegen.cs | 25 ++-------------- .../Internal/Declarations/ClassDeclaration.cs | 1 + .../Internal/OptimizingIr/Model/Module.cs | 1 - .../Internal/OptimizingIr/Model/Type.cs | 1 + .../Symbols/Source/SourceClassSymbol.cs | 1 + 12 files changed, 33 insertions(+), 50 deletions(-) diff --git a/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs b/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs index 50583b8fa..dcdcdd0c5 100644 --- a/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs @@ -119,7 +119,7 @@ public async Task WhileLoop() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("i", null, LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "i", null, LiteralExpression(0))), ExpressionStatement(WhileExpression( RelationalExpression(NameExpression("i"), ComparisonElement(LessThan, LiteralExpression(10))), BlockExpression( @@ -184,7 +184,7 @@ public async Task ConditionalGotoInAssignment() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", null, IfExpression( + DeclarationStatement(VariableDeclaration(true, "x", null, IfExpression( NameExpression("b"), GotoExpression(NameLabel("noassign")), LiteralExpression(1)))), diff --git a/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs b/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs index 546027ccc..27999f55c 100644 --- a/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs @@ -20,8 +20,8 @@ public void UseOfUnassignedVariable() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), - DeclarationStatement(VariableDeclaration("y", NameType("int32"), NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "y", NameType("int32"), NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -46,8 +46,8 @@ public void UseOfAssignedVariable() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"), LiteralExpression(0))), - DeclarationStatement(VariableDeclaration("y", NameType("int32"), NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))), + DeclarationStatement(VariableDeclaration(true, "y", NameType("int32"), NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -72,12 +72,12 @@ public void UseOfConditionallyAssignedVariable() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(IfExpression( NameExpression("b"), StatementExpression(ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(42)))), null as ExpressionSyntax)), - DeclarationStatement(VariableDeclaration("y", NameType("int32"), NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", NameType("int32"), NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -103,12 +103,12 @@ public void UseOfConditionallyAssignedVariableOnBothBranches() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(IfExpression( NameExpression("b"), BinaryExpression(NameExpression("x"), Assign, LiteralExpression(42)), BinaryExpression(NameExpression("x"), Assign, LiteralExpression(0)))), - DeclarationStatement(VariableDeclaration("y", NameType("int32"), NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", NameType("int32"), NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -133,12 +133,12 @@ public void JumpingMidAssignment() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"), IfExpression( + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"), IfExpression( NameExpression("b"), GotoExpression(NameLabel("end")), LiteralExpression(42)))), DeclarationStatement(LabelDeclaration("end")), - DeclarationStatement(VariableDeclaration("y", NameType("int32"), NameExpression("x"))))))); + DeclarationStatement(VariableDeclaration(true, "y", NameType("int32"), NameExpression("x"))))))); // Act var compilation = CreateCompilation(tree); @@ -163,7 +163,7 @@ public void CompoundAssigningUnassignedVariable() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(BinaryExpression(NameExpression("x"), PlusAssign, LiteralExpression(42))))))); // Act @@ -195,8 +195,8 @@ public void UseVariableAssignedLater() ExpressionStatement(WhileExpression( NameExpression("b"), BlockExpression( - DeclarationStatement(VariableDeclaration("x", NameType("int32"))), - DeclarationStatement(VariableDeclaration("y", NameType("int32"), NameExpression("x"))), + DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), + DeclarationStatement(VariableDeclaration(true, "y", NameType("int32"), NameExpression("x"))), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(42)))))))))); // Act @@ -215,7 +215,7 @@ public void GlobalImmutableInitialized() // Arrange // val x: int32 = 0; var tree = SyntaxTree.Create(CompilationUnit( - ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0)))); + ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0)))); // Act var compilation = CreateCompilation(tree); @@ -232,7 +232,7 @@ public void GlobalImmutableNotInitialized() // Arrange // val x: int32; var tree = SyntaxTree.Create(CompilationUnit( - ImmutableVariableDeclaration("x", NameType("int32")))); + ImmutableVariableDeclaration(true, "x", NameType("int32")))); // Act var compilation = CreateCompilation(tree); diff --git a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs index 4fc658be4..77b48f886 100644 --- a/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SemanticModelTests.cs @@ -505,6 +505,6 @@ public void GetReferencedSymbolFromSourceClassSymbol() Assert.NotNull(classSymbol); Assert.Equal("Foo", classSymbol.Name); Assert.Empty(semanticModel.Diagnostics); - Assert.Equal("bar", classSymbol.Members.Single().Name); + Assert.Equal("bar", classSymbol.Members.Single(x => x.Name == "bar").Name); } } diff --git a/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs b/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs index ff8c226dc..d3669c9e9 100644 --- a/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs @@ -19,7 +19,7 @@ public void AssignImmutableOnce() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0))))))); + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))))))); // Act var compilation = CreateCompilation(tree); @@ -43,7 +43,7 @@ public void AssignImmutableTwice() ParameterList(), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0))), + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0))), ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(1))))))); // Act @@ -69,7 +69,7 @@ public void AssignImmutableInMutuallyExclusiveBranches() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"))), + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(IfExpression( NameExpression("b"), StatementExpression(ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(1)))), @@ -98,7 +98,7 @@ public void ConditionallyAndThenUnconditionallyAssignImmutable() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"))), + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(IfExpression( NameExpression("b"), StatementExpression(ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(1)))))), @@ -127,7 +127,7 @@ public void AssignImmutableInLoop() ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( - DeclarationStatement(ImmutableVariableDeclaration("x", NameType("int32"))), + DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))), ExpressionStatement(WhileExpression( NameExpression("b"), StatementExpression(ExpressionStatement(BinaryExpression(NameExpression("x"), Assign, LiteralExpression(1)))))))))); @@ -151,7 +151,7 @@ public void GlobalImmutableReassigned() // x = 1; // } var tree = SyntaxTree.Create(CompilationUnit( - ImmutableVariableDeclaration("x", NameType("int32"), LiteralExpression(0)), + ImmutableVariableDeclaration(true, "x", NameType("int32"), LiteralExpression(0)), FunctionDeclaration( "foo", ParameterList(), diff --git a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs index 42ac22d3c..f9479a94b 100644 --- a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs @@ -4065,6 +4065,7 @@ public void ReturningInGlobalBlockIsIllegal() var main = SyntaxTree.Create(CompilationUnit( ImmutableVariableDeclaration( + true, "a", null, BlockExpression(ExpressionStatement(ReturnExpression(LiteralExpression(4))))))); diff --git a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs index 43cd29b2e..f8abe8699 100644 --- a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs @@ -2485,6 +2485,7 @@ public void AssigningListToArrayTypeIsIllegal() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( + true, "x", GenericType(NameType("Array"), NameType("int32")), CallExpression(NameExpression("List")))))))); diff --git a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs index 6941594bf..08f6e8ea5 100644 --- a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs +++ b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs @@ -2096,7 +2096,7 @@ public void TestEmptyGenericParameterList() this.T(TokenKind.GreaterThan); } this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); { @@ -2119,7 +2119,7 @@ func foo(x: List<>) {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "foo"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); { this.N(); { diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 69d4f3e9c..fe22feb13 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -461,9 +461,9 @@ private void EncodeModule( var startProcIndex = procIndex; // Go through globals - foreach (var global in module.Globals) + foreach (var global in module.Fields) { - this.EncodeGlobal(global); + this.EncodeField(global); ++fieldIndex; } @@ -724,27 +724,6 @@ ref int procIndex return createdClass; } - private FieldDefinitionHandle EncodeField(FieldSymbol field) - { - var visibility = field.Visibility switch - { - Api.Semantics.Visibility.Public => FieldAttributes.Public, - Api.Semantics.Visibility.Internal => FieldAttributes.Assembly, - Api.Semantics.Visibility.Private => FieldAttributes.Private, - _ => throw new IndexOutOfRangeException(nameof(field.Visibility)), - }; - var mutability = field.IsMutable ? default : FieldAttributes.InitOnly; - - // Definition - return this.AddFieldDefinition( - attributes: visibility | mutability, - name: field.Name, - signature: this.EncodeFieldSignature(field)); - } - - private BlobHandle EncodeFieldSignature(FieldSymbol field) => - this.EncodeBlob(e => this.EncodeSignatureType(e.Field().Type(), field.Type)); - private IEnumerable ScalarConstantTypes => [ this.WellKnownTypes.SystemSByte, this.WellKnownTypes.SystemInt16, diff --git a/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs index 17f491670..a1e43c269 100644 --- a/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs @@ -3,6 +3,7 @@ using System.Collections.Immutable; using System.Linq; using Draco.Compiler.Api.Syntax; +using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.Declarations; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index 779fa3920..e2c6d9d87 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -21,7 +21,6 @@ internal sealed class Module : IModule public IDictionary Types => this.types; IReadOnlyDictionary IModule.Types => this.types; - public IReadOnlySet Globals => this.globals; public IReadOnlySet Fields => this.fields; public Procedure GlobalInitializer { get; } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs index ac39a13a7..e7138610a 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs @@ -2,6 +2,7 @@ using System.Collections.Immutable; using System.Linq; using Draco.Compiler.Internal.Symbols; +using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.OptimizingIr.Model; internal class Type(Module declaringModule, TypeSymbol symbol) : IType diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 5d8303014..493b0ca89 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -10,6 +10,7 @@ using Draco.Compiler.Internal.Binding; using Draco.Compiler.Internal.Declarations; using Draco.Compiler.Internal.Symbols.Synthetized; +using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.Symbols.Source; From 2ff6b9946ed8563fe33a7aacdd6e21e20d32b9f7 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 27 Oct 2024 11:57:49 +0100 Subject: [PATCH 037/109] fixed special name logic --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index fe22feb13..5abc40154 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -569,7 +569,7 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure, string? spe // Determine attributes var attributes = MethodAttributes.HideBySig | visibility; if (procedure.Symbol.IsStatic) attributes |= MethodAttributes.Static; - if (procedure.Symbol.IsSpecialName) attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; + if (specialName != null) attributes |= MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; // Parameters var parameterList = this.NextParameterHandle; From f7539df13f55755a6ed4b4d3cc77be03f474f5a4 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 27 Oct 2024 15:49:45 +0100 Subject: [PATCH 038/109] self review --- .../EndToEnd/CodeExecutionTests.cs | 62 ------------------- .../EndToEnd/CompilingCodeTests.cs | 49 +++++++++++++++ .../Semantics/DocumentationCommentsTests.cs | 5 +- .../Semantics/LocalFunctionsTests.cs | 3 +- .../Semantics/TypeCheckingTests.cs | 21 ++++--- src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs | 1 - .../OptimizingIr/Codegen/ClassCodegen.cs | 4 +- .../OptimizingIr/Codegen/LocalCodegen.cs | 7 +-- .../Symbols/Source/SourceClassSymbol.cs | 1 - .../Symbols/Syntax/SyntaxFunctionSymbol.cs | 1 - src/Draco.Compiler/Internal/Syntax/Lexer.cs | 1 - src/Draco.Compiler/Internal/Syntax/Parser.cs | 2 +- 12 files changed, 71 insertions(+), 86 deletions(-) delete mode 100644 src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs diff --git a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs deleted file mode 100644 index 85fcfcf13..000000000 --- a/src/Draco.Compiler.Tests/EndToEnd/CodeExecutionTests.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using static Draco.Compiler.Tests.TestUtilities; - -namespace Draco.Compiler.Tests.EndToEnd; - -[Collection(nameof(NoParallelizationCollectionDefinition))] -public class CodeExecutionTests -{ - [Fact] - public void ClassHelloWorld() - { - var assembly = CompileToAssembly(""" - import System.Console; - - class Foo { - func bar() { - WriteLine("Hello, World!"); - } - } - """); - - var stringWriter = new StringWriter(); - _ = Invoke(assembly: assembly, stdout: stringWriter, methodName: "bar", moduleName: "FreeFunctions.Foo"); - - Assert.Equal($"Hello, World!{Environment.NewLine}", stringWriter.ToString(), ignoreLineEndingDifferences: true); - } - - [Fact] - public void InstanceField() - { - var assembly = CompileToAssembly(""" - import System.Console; - - func main(): int32 { - var foo = Foo(); - foo.increment(); - return foo.get(); - } - - class Foo { - field var i: int32; - public func increment(this) { - this.i += 1; - } - - public func get(this): int32 { - return this.i; - } - } - - """); - - var stringWriter = new StringWriter(); - var value = Invoke(assembly: assembly, stdout: stringWriter); - Assert.Equal(1, value); - - } -} diff --git a/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs index 23186003c..64669b26b 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs @@ -999,4 +999,53 @@ func outer(x: int32): int32 { Assert.Equal(3, result); } + + [Fact] + public void ClassHelloWorld() + { + var assembly = CompileToAssembly(""" + import System.Console; + + class Foo { + func bar() { + WriteLine("Hello, World!"); + } + } + """); + + var stringWriter = new StringWriter(); + _ = Invoke(assembly: assembly, stdout: stringWriter, methodName: "bar", moduleName: "FreeFunctions.Foo"); + + Assert.Equal($"Hello, World!{Environment.NewLine}", stringWriter.ToString(), ignoreLineEndingDifferences: true); + } + + [Fact] + public void InstanceField() + { + var assembly = CompileToAssembly(""" + import System.Console; + + func main(): int32 { + var foo = Foo(); + foo.increment(); + return foo.get(); + } + + class Foo { + field var i: int32; + public func increment(this) { + this.i += 1; + } + + public func get(this): int32 { + return this.i; + } + } + + """); + + var stringWriter = new StringWriter(); + var value = Invoke(assembly: assembly, stdout: stringWriter); + Assert.Equal(1, value); + } } diff --git a/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs b/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs index 9835d9b2c..36780e878 100644 --- a/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/DocumentationCommentsTests.cs @@ -94,7 +94,8 @@ public void VariableDocumentationComment(string docComment) // Arrange var tree = SyntaxTree.Create(CompilationUnit( WithDocumentation(VariableDeclaration( - true, "x", + true, + "x", null, LiteralExpression(0)), docComment))); @@ -566,7 +567,7 @@ namespace TestNamespace; public class TestClass { {{CreateXmlDocComment(originalDocs)}} - public int TestMethod(int arg1, int arg2) => arg1 + arg2; + public int TestMethod(int arg1, int arg2) => arg1 + arg2; } """, xmlDocStream: xmlStream); diff --git a/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs b/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs index 17df97e74..2339fb4f3 100644 --- a/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs @@ -98,7 +98,8 @@ public void LocalVariableIncompatibleType() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", NameType("int32"), StringExpression("Hello")))))))))); diff --git a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs index f8abe8699..6583a3585 100644 --- a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs @@ -166,7 +166,8 @@ public void LocalVariableIncompatibleType() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", NameType("int32"), StringExpression("Hello"))))))); @@ -317,7 +318,8 @@ public void GlobalVariableIncompatibleType() // Arrange var tree = SyntaxTree.Create(CompilationUnit( VariableDeclaration( - true, "x", + true, + "x", NameType("int32"), StringExpression("Hello")))); @@ -495,7 +497,8 @@ public void IfElseTypeMismatch() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", value: IfExpression( condition: LiteralExpression(true), then: LiteralExpression(0), @@ -603,7 +606,8 @@ public void NoOverloadForOperator() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", value: BinaryExpression(LiteralExpression(1), Plus, StringExpression("Hello")))))))); var xDecl = tree.GetNode(0); @@ -1367,7 +1371,8 @@ public void InferGenericFunctionParameterTypeFromUse() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", null, CallExpression(NameExpression("identity"), LiteralExpression(0)))))))); @@ -2056,7 +2061,8 @@ public void IfStatementCommonTypeResult() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", null, IfExpression( LiteralExpression(true), @@ -2223,7 +2229,8 @@ public void StringAssignableToObject() null, BlockFunctionBody( DeclarationStatement(VariableDeclaration( - true, "x", + true, + "x", NameType("object"), StringExpression("Hello"))))))); diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs index 0e0eae750..078baffe7 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs @@ -1,6 +1,5 @@ using System; using System.Diagnostics; -using System.Security.Principal; namespace Draco.Compiler.Api.Syntax; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs index d8aa0e633..18aef6e94 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -19,7 +19,7 @@ internal sealed class ClassCodegen(ModuleCodegen moduleCodegen, Type @class) : S private Compilation Compilation => moduleCodegen.Compilation; private bool EmitSequencePoints => moduleCodegen.EmitSequencePoints; - // TODO: Copypasta from ModuleCodegen + // Copypasta from ModuleCodegen public override void VisitFunction(FunctionSymbol functionSymbol) { if (functionSymbol.Body is null) return; @@ -44,8 +44,6 @@ public override void VisitField(FieldSymbol fieldSymbol) // No-op, the Class model reads it up from the symbol } - // TODO: Copypasta from ModuleCodegen - // TODO: Except we check for syntax not being null because we can have synthetized symbols private BoundNode RewriteBody(BoundNode body) { // If needed, inject sequence points diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs index df2d18e37..57fa3b5d0 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/LocalCodegen.cs @@ -1,5 +1,4 @@ using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using Draco.Compiler.Api; using Draco.Compiler.Internal.Binding; @@ -37,11 +36,7 @@ public LocalCodegen(Compilation compilation, Procedure procedure) } private void Compile(BoundStatement stmt) => stmt.Accept(this); - private IOperand Compile(BoundExpression expr) - { - var val = expr.Accept(this); - return val; - } + private IOperand Compile(BoundExpression expr) => expr.Accept(this); private void AttachBlock(BasicBlock basicBlock) { diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 493b0ca89..ad6bffe4f 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -77,7 +77,6 @@ private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvide private ImmutableArray BindMembers(IBinderProvider binder) { - if (this.DeclaringSyntax.Body is EmptyClassBodySyntax) return [new DefaultConstructorSymbol(this)]; var bodyClass = this.DeclaringSyntax.Body as BlockClassBodySyntax; diff --git a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs index 359b9dc2c..77f3e9a2a 100644 --- a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs @@ -1,6 +1,5 @@ using System.Collections.Immutable; using System.Linq; -using System.Reflection.Metadata.Ecma335; using System.Threading; using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 71a2d1690..83fd7ca7b 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -326,7 +326,6 @@ Unit TakeWithText(TokenKind tokenKind, int length) while (IsIdent(this.Peek(offset))) ++offset; var ident = this.Advance(offset); // Remap keywords - // TODO: Any better/faster way? var tokenKind = ident.Span switch { "and" => TokenKind.KeywordAnd, diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 6032eded2..7d9b594e7 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -574,7 +574,7 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, Sy { TokenKind.Semicolon => this.ParseEmptyClassBody(), TokenKind.CurlyOpen => this.ParseBlockClassBody(), - _ => throw new NotImplementedException(),// TODO + _ => throw new NotImplementedException() }; /// From 8035ae4bab58e461b1e99b3610ff301b9f6afffd Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 27 Oct 2024 18:33:38 +0100 Subject: [PATCH 039/109] Some pr feedback. --- .../EndToEnd/CompilingCodeTests.cs | 53 +++++++++---------- .../Api/Syntax/SyntaxFactory.cs | 5 +- .../Internal/Binding/BinderCache.cs | 3 +- .../Internal/Binding/Binder_Expression.cs | 28 ++++++---- .../Internal/Binding/Binder_Lookup.cs | 21 -------- .../Internal/Binding/ClassBinder.cs | 3 +- .../Internal/Binding/LocalBinder.cs | 6 +-- .../Internal/Codegen/CilCodegen.cs | 31 ++++++----- .../OptimizingIr/Codegen/ClassCodegen.cs | 1 - .../Internal/OptimizingIr/Model/Field.cs | 3 +- .../Symbols/Error/ErrorThisParameterSymbol.cs | 10 ++++ .../Internal/Symbols/FunctionSymbol.cs | 1 - src/Draco.Compiler/Internal/Syntax/Lexer.cs | 1 + 13 files changed, 83 insertions(+), 83 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs diff --git a/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs index 64669b26b..3a899204f 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs @@ -1004,14 +1004,14 @@ func outer(x: int32): int32 { public void ClassHelloWorld() { var assembly = CompileToAssembly(""" - import System.Console; + import System.Console; - class Foo { - func bar() { - WriteLine("Hello, World!"); - } - } - """); + class Foo { + func bar() { + WriteLine("Hello, World!"); + } + } + """); var stringWriter = new StringWriter(); _ = Invoke(assembly: assembly, stdout: stringWriter, methodName: "bar", moduleName: "FreeFunctions.Foo"); @@ -1023,26 +1023,25 @@ func bar() { public void InstanceField() { var assembly = CompileToAssembly(""" - import System.Console; - - func main(): int32 { - var foo = Foo(); - foo.increment(); - return foo.get(); - } - - class Foo { - field var i: int32; - public func increment(this) { - this.i += 1; - } - - public func get(this): int32 { - return this.i; - } - } - - """); + import System.Console; + + func main(): int32 { + var foo = Foo(); + foo.increment(); + return foo.get(); + } + + class Foo { + field var i: int32; + public func increment(this) { + this.i += 1; + } + + public func get(this): int32 { + return this.i; + } + } + """); var stringWriter = new StringWriter(); var value = Invoke(assembly: assembly, stdout: stringWriter); diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index 74f853846..a0a11b340 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -257,8 +257,7 @@ public static ClassDeclarationSyntax ClassDeclaration( null, name, generics, - BlockClassBody(members) - ); + BlockClassBody(members)); public static IndexExpressionSyntax IndexExpression(ExpressionSyntax indexed, params ExpressionSyntax[] indices) => IndexExpression(indexed, SeparatedSyntaxList(Comma, indices)); @@ -267,7 +266,7 @@ public static IndexExpressionSyntax IndexExpression(ExpressionSyntax indexed, pa public static LiteralExpressionSyntax LiteralExpression(int value) => LiteralExpression(Integer(value)); public static LiteralExpressionSyntax LiteralExpression(bool value) => LiteralExpression(value ? KeywordTrue : KeywordFalse); public static StringExpressionSyntax StringExpression(string value) => - StringExpression(LineStringStart, SyntaxList(TextStringPart(value)), LineStringEnd); + StringExpression(LineStringStart, [TextStringPart(value)], LineStringEnd); public static TextStringPartSyntax TextStringPart(string value) => TextStringPart(Token(TokenKind.StringContent, value, value)); diff --git a/src/Draco.Compiler/Internal/Binding/BinderCache.cs b/src/Draco.Compiler/Internal/Binding/BinderCache.cs index b773fbe9c..50ab5d131 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderCache.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderCache.cs @@ -103,11 +103,10 @@ private ClassBinder BuildClassDeclarationBinder(ClassDeclarationSyntax syntax) var parent = UnwrapFromImportBinder(binder); var classSymbol = parent.DeclaredSymbols .OfType() - .FirstOrDefault(member => member.DeclaringSyntax == syntax); // should we shove that in an helper ? + .First(member => member.DeclaringSyntax == syntax); // should we shove that in a helper ? return new ClassBinder(binder, classSymbol); } - private Binder BuildFunctionBodyBinder(FunctionBodySyntax syntax) { Debug.Assert(syntax.Parent is not null); diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index 064cd3b16..e5ce3ba7e 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Draco.Compiler.Api.Diagnostics; +using Draco.Compiler.Api.Semantics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding.Tasks; using Draco.Compiler.Internal.BoundTree; @@ -14,7 +15,15 @@ using Draco.Compiler.Internal.Symbols.Error; using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Symbols.Syntax; -using Draco.Compiler.Internal.Symbols.Synthetized; +using FieldSymbol = Draco.Compiler.Internal.Symbols.FieldSymbol; +using FunctionGroupSymbol = Draco.Compiler.Internal.Symbols.Synthetized.FunctionGroupSymbol; +using FunctionSymbol = Draco.Compiler.Internal.Symbols.FunctionSymbol; +using LabelSymbol = Draco.Compiler.Internal.Symbols.LabelSymbol; +using LocalSymbol = Draco.Compiler.Internal.Symbols.LocalSymbol; +using ModuleSymbol = Draco.Compiler.Internal.Symbols.ModuleSymbol; +using ParameterSymbol = Draco.Compiler.Internal.Symbols.ParameterSymbol; +using PropertySymbol = Draco.Compiler.Internal.Symbols.PropertySymbol; +using TypeSymbol = Draco.Compiler.Internal.Symbols.TypeSymbol; namespace Draco.Compiler.Internal.Binding; @@ -719,20 +728,21 @@ private async BindingTask BindIndexExpression(IndexExpressionSy private BindingTask BindThisExpression(ThisExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { - var thisArg = ((SyntaxFunctionSymbol)this.ContainingSymbol!).ThisArgument; - if (thisArg == null) + var function = ((SyntaxFunctionSymbol)this.ContainingSymbol!); + var thisArg = function.ThisArgument as ParameterSymbol; + if (thisArg is null) { diagnostics.Add(Diagnostic.Create( - template: SymbolResolutionErrors.NoThisInStaticMethod, - location: syntax.Location, - formatArgs: [this.ContainingSymbol!.Name])); - + template: SymbolResolutionErrors.NoThisInStaticMethod, + location: syntax.Location, + formatArgs: [this.ContainingSymbol!.Name])); + var type = function.ContainingSymbol as TypeSymbol ?? WellKnownTypes.ErrorType; + thisArg = new ErrorThisParameterSymbol(type, function); } - var boundThis = new BoundParameterExpression(syntax, thisArg); // todo: what should i do here ? + var boundThis = new BoundParameterExpression(syntax, thisArg); return BindingTask.FromResult(boundThis); } - private async BindingTask BindGenericExpression(GenericExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { var instantiatedTask = this.BindExpression(syntax.Instantiated, constraints, diagnostics); diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs b/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs index 125dfe987..ed4abe374 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs @@ -53,27 +53,6 @@ internal Symbol LookupTypeSymbol(string name, SyntaxNode reference, DiagnosticBa var result = this.LookupInternal(name, BinderFacts.IsTypeSymbol, reference); return result.GetType(name, reference, diagnostics); } - /// - /// Looks up the declaring type of the current scope. - /// - /// The syntax referencing the symbol. - /// The diagnostics are added here from lookup. - /// - /// - internal TypeSymbol LookupDeclaringType(SyntaxNode reference, DiagnosticBag diagnostics) - { - foreach (var scope in this.AncestorChain) - { - if (scope is ClassBinder classBinder) - { - return classBinder.ContainingSymbol; - } - } - diagnostics.Add(Diagnostic.Create( - template: SymbolResolutionErrors.NoTypeInstanceToReference, - location: reference.Location)); - return WellKnownTypes.ErrorType; - } /// /// Looks up a symbol that can be used in label-context. diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs index e8849b458..eb0aa60d5 100644 --- a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -8,6 +8,7 @@ using Draco.Compiler.Internal.Symbols.Source; namespace Draco.Compiler.Internal.Binding; + internal sealed class ClassBinder(Binder parent, TypeSymbol symbol) : Binder(parent) { public override TypeSymbol ContainingSymbol => this.symbol; @@ -39,7 +40,5 @@ internal override void LookupLocal(LookupResult result, string name, ref LookupF result.Add(member); break; } - - flags |= LookupFlags.DisallowLocals | LookupFlags.AllowGlobals; } } diff --git a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs index 8a3b5e38b..57c99d461 100644 --- a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs @@ -169,9 +169,9 @@ private void Build() { FunctionDeclarationSyntax function => new SourceFunctionSymbol(this.ContainingSymbol, function), ParameterSyntax parameter => new SourceParameterSymbol((FunctionSymbol)this.ContainingSymbol, parameter), - VariableDeclarationSyntax variable => variable.FieldKeyword != null ? - new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, variable) : - new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable), + VariableDeclarationSyntax variable => variable.FieldKeyword is null ? + new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable) : + new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, variable), LabelDeclarationSyntax label => new SourceLabelSymbol(this.ContainingSymbol, label), _ => null, }; diff --git a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs index 4db224987..3ae539d86 100644 --- a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs @@ -81,6 +81,7 @@ public CilCodegen(MetadataCodegen metadataCodegen, IProcedure procedure) } private int? GetLocalIndex(LocalSymbol local) => this.GetAllocatedLocal(local)?.Index; + private int? GetRegisterIndex(Register register) { if (SymbolEqualityComparer.Default.Equals(register.Type, WellKnownTypes.Unit)) return null; @@ -91,6 +92,7 @@ public CilCodegen(MetadataCodegen metadataCodegen, IProcedure procedure) allocatedRegister = this.allocatedLocals.Count + this.allocatedRegisters.Count; this.allocatedRegisters.Add(register, allocatedRegister); } + return allocatedRegister; } @@ -108,6 +110,7 @@ private LabelHandle GetLabel(IBasicBlock block) label = this.InstructionEncoder.DefineLabel(); this.labels.Add(block, label); } + return label; } @@ -128,11 +131,13 @@ private void EncodeBasicBlock(IBasicBlock basicBlock) private void EncodeInstruction(IInstruction instruction) { var operandEnumerator = instruction.Operands.GetEnumerator(); + IOperand NextOperand() { if (!operandEnumerator!.MoveNext()) throw new InvalidOperationException(); return operandEnumerator.Current; } + IEnumerable RemainingOperands() { while (operandEnumerator!.MoveNext()) yield return operandEnumerator.Current; @@ -221,19 +226,16 @@ IEnumerable RemainingOperands() this.LoadLocal(local); break; } - case FieldSymbol { IsStatic: true } global: - { - this.InstructionEncoder.OpCode(ILOpCode.Ldsfld); - this.EncodeToken(global); - break; - } case FieldSymbol field: - this.InstructionEncoder.OpCode(ILOpCode.Ldfld); + { + this.InstructionEncoder.OpCode(field.IsStatic ? ILOpCode.Ldsfld : ILOpCode.Ldfld); this.EncodeToken(field); break; + } default: throw new InvalidOperationException(); } + // Just copy to the target local this.StoreRegister(load.Target); break; @@ -259,6 +261,7 @@ IEnumerable RemainingOperands() loadElement.Target.Type, loadElement.Indices.Count)); } + // Store result this.StoreRegister(loadElement.Target); break; @@ -281,19 +284,15 @@ IEnumerable RemainingOperands() this.EncodePush(NextOperand()); this.StoreLocal(local); break; - case FieldSymbol { IsStatic: true } global: - this.EncodePush(NextOperand()); - this.InstructionEncoder.OpCode(ILOpCode.Stsfld); - this.EncodeToken(global); - break; case FieldSymbol field: this.EncodePush(NextOperand()); - this.InstructionEncoder.OpCode(ILOpCode.Stfld); + this.InstructionEncoder.OpCode(field.IsStatic ? ILOpCode.Stsfld : ILOpCode.Stfld); this.EncodeToken(field); break; default: throw new InvalidOperationException(); } + break; } case StoreElementInstruction storeElement: @@ -320,6 +319,7 @@ IEnumerable RemainingOperands() targetStorageType, storeElement.Indices.Count)); } + break; } case StoreFieldInstruction storeField: @@ -360,6 +360,7 @@ IEnumerable RemainingOperands() default: throw new InvalidOperationException(); } + break; } case CallInstruction call: @@ -415,6 +416,7 @@ IEnumerable RemainingOperands() newArr.ElementType, newArr.Dimensions.Count)); } + // Store result this.StoreRegister(newArr.Target); break; @@ -521,6 +523,7 @@ private void EncodePush(IOperand operand) default: throw new NotImplementedException(); } + break; case DefaultValue d: { @@ -556,8 +559,10 @@ private void StoreRegister(Register register) // Need to pop this.InstructionEncoder.OpCode(ILOpCode.Pop); } + return; } + this.InstructionEncoder.StoreLocal(index.Value); } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs index 18aef6e94..b92cb5ef0 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -10,7 +10,6 @@ namespace Draco.Compiler.Internal.OptimizingIr.Codegen; - /// /// Generates IR code for a class. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs index 8e47b1c1d..4c53f33b6 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs @@ -2,7 +2,8 @@ using Draco.Compiler.Internal.Symbols; namespace Draco.Compiler.Internal.OptimizingIr.Model; -internal class Field(FieldSymbol symbol, Type declaringType) : IField + +internal sealed class Field(FieldSymbol symbol, Type declaringType) : IField { public FieldSymbol Symbol { get; } = symbol; diff --git a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs new file mode 100644 index 000000000..c7632c3d5 --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs @@ -0,0 +1,10 @@ +using Draco.Compiler.Internal.Binding; +using Draco.Compiler.Internal.Symbols.Source; + +namespace Draco.Compiler.Internal.Symbols.Error; + +internal class ErrorThisParameterSymbol(TypeSymbol type, FunctionSymbol containingSymbol) : ParameterSymbol +{ + public override TypeSymbol Type { get; } = type; + public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; +} diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index 4fecc512e..ed0f5a1f9 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -82,7 +82,6 @@ public delegate IOperand CodegenDelegate( ? null : this.ContainingSymbol as TypeSymbol; - /// /// The parameters of this function. /// diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 83fd7ca7b..c818e6f77 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -336,6 +336,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) "for" => TokenKind.KeywordFor, "func" => TokenKind.KeywordFunc, "goto" => TokenKind.KeywordGoto, + "global" => TokenKind.KeywordGlobal, "if" => TokenKind.KeywordIf, "import" => TokenKind.KeywordImport, "in" => TokenKind.KeywordIn, From fb297e0b462250f56173e2a06c668dae702aac95 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Sun, 27 Oct 2024 22:06:06 +0100 Subject: [PATCH 040/109] Removed unused field ir model. --- .../Internal/OptimizingIr/Model/Field.cs | 18 ----------- .../Internal/OptimizingIr/Model/IField.cs | 32 ------------------- 2 files changed, 50 deletions(-) delete mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs delete mode 100644 src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs deleted file mode 100644 index 4c53f33b6..000000000 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Field.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using Draco.Compiler.Internal.Symbols; - -namespace Draco.Compiler.Internal.OptimizingIr.Model; - -internal sealed class Field(FieldSymbol symbol, Type declaringType) : IField -{ - public FieldSymbol Symbol { get; } = symbol; - - public string Name => this.Symbol.Name; - - public Type DeclaringType { get; } = declaringType; - IType IField.DeclaringType => this.DeclaringType; - - public IReadOnlyList Attributes => this.Symbol.Attributes; - - public TypeSymbol Type => this.Symbol.Type; -} diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs deleted file mode 100644 index a818dfb2b..000000000 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IField.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; -using Draco.Compiler.Internal.Symbols; - -namespace Draco.Compiler.Internal.OptimizingIr.Model; - -/// -/// Read-only interface of a field. -/// -internal interface IField -{ - public FieldSymbol Symbol { get; } - - /// - /// The name of this field. - /// - public string Name { get; } - - /// - /// The type this procedure is defined in. - /// - public IType DeclaringType { get; } - - /// - /// The attributes on this field. - /// - public IReadOnlyList Attributes { get; } - - /// - /// The type of this field. - /// - public TypeSymbol Type { get; } -} From 56fd7f45b9d4ce3beb2d37ff274ad1c9da6a0cc0 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 28 Oct 2024 00:45:48 +0100 Subject: [PATCH 041/109] Type => Class, + ran namespace simplification. --- .../Internal/Codegen/MetadataCodegen.cs | 16 ++++++++-------- .../OptimizingIr/Codegen/ClassCodegen.cs | 2 +- .../OptimizingIr/Model/{Type.cs => Class.cs} | 6 +++--- .../OptimizingIr/Model/{IType.cs => IClass.cs} | 2 +- .../Internal/OptimizingIr/Model/IModule.cs | 2 +- .../Internal/OptimizingIr/Model/IProcedure.cs | 2 +- .../Internal/OptimizingIr/Model/Module.cs | 12 ++++++------ .../Internal/OptimizingIr/Model/Procedure.cs | 6 +++--- .../Internal/Symbols/FunctionSymbol.cs | 2 +- src/Draco.Compiler/Internal/Symbols/Symbol.cs | 10 +++++----- .../Internal/Symbols/TypeParameterSymbol.cs | 2 +- .../Internal/Symbols/TypeSymbol.cs | 2 +- .../Internal/Symbols/WellKnownTypes.cs | 4 ++-- src/Draco.DebugAdapter/DracoDebugAdapter.cs | 6 +++--- src/Draco.SourceGeneration/Lsp/Translator.cs | 2 +- 15 files changed, 38 insertions(+), 38 deletions(-) rename src/Draco.Compiler/Internal/OptimizingIr/Model/{Type.cs => Class.cs} (87%) rename src/Draco.Compiler/Internal/OptimizingIr/Model/{IType.cs => IClass.cs} (97%) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 5abc40154..905e5289c 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -655,7 +655,7 @@ private BlobHandle EncodeAttributeSignature(AttributeInstance attribute) } private TypeDefinitionHandle EncodeClass( - IType type, + IClass @class, TypeDefinitionHandle? parent, ref int fieldIndex, ref int procIndex @@ -664,7 +664,7 @@ ref int procIndex var startFieldIndex = fieldIndex; var startProcIndex = procIndex; - var visibility = (type.Symbol.Visibility, parent) switch + var visibility = (@class.Symbol.Visibility, parent) switch { (Api.Semantics.Visibility.Public, not null) => TypeAttributes.NestedPublic, (Api.Semantics.Visibility.Public, null) => TypeAttributes.Public, @@ -674,19 +674,19 @@ ref int procIndex var attributes = visibility | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed; - if (type.Symbol.IsValueType) attributes |= TypeAttributes.SequentialLayout; // AutoLayout = 0. + if (@class.Symbol.IsValueType) attributes |= TypeAttributes.SequentialLayout; // AutoLayout = 0. var createdClass = this.AddTypeDefinition( attributes, null, - type.Name, - type.Symbol.IsValueType ? this.systemValueTypeReference : this.systemObjectReference, + @class.Name, + @class.Symbol.IsValueType ? this.systemValueTypeReference : this.systemObjectReference, fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex) ); // Procedures - foreach (var proc in type.Methods.Values) + foreach (var proc in @class.Methods.Values) { if (proc.Symbol is DefaultConstructorSymbol ctor) { @@ -703,14 +703,14 @@ ref int procIndex } // Fields - foreach (var field in type.Fields) + foreach (var field in @class.Fields) { this.EncodeField(field); ++fieldIndex; } // If this is a valuetype without fields, we add .pack 0 and .size 1 - if (type.Symbol.IsValueType && type.Fields.Count == 0) + if (@class.Symbol.IsValueType && @class.Fields.Count == 0) { this.MetadataBuilder.AddTypeLayout( type: createdClass, diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs index b92cb5ef0..5d3ae6088 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -13,7 +13,7 @@ namespace Draco.Compiler.Internal.OptimizingIr.Codegen; /// /// Generates IR code for a class. /// -internal sealed class ClassCodegen(ModuleCodegen moduleCodegen, Type @class) : SymbolVisitor +internal sealed class ClassCodegen(ModuleCodegen moduleCodegen, Class @class) : SymbolVisitor { private Compilation Compilation => moduleCodegen.Compilation; private bool EmitSequencePoints => moduleCodegen.EmitSequencePoints; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs similarity index 87% rename from src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs rename to src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs index e7138610a..7a49c61fa 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Type.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs @@ -5,16 +5,16 @@ using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.OptimizingIr.Model; -internal class Type(Module declaringModule, TypeSymbol symbol) : IType +internal class Class(Module declaringModule, TypeSymbol symbol) : IClass { public TypeSymbol Symbol { get; } = symbol; public string Name => this.Symbol.Name; public Module DeclaringModule { get; } = declaringModule; - IModule IType.DeclaringModule => this.DeclaringModule; + IModule IClass.DeclaringModule => this.DeclaringModule; public Assembly Assembly => this.DeclaringModule.Assembly; - IAssembly IType.Assembly => this.Assembly; + IAssembly IClass.Assembly => this.Assembly; public IReadOnlyList Generics => this.Symbol.GenericParameters; public IReadOnlyDictionary Methods => this.methods; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs similarity index 97% rename from src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs rename to src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index 668ceb855..f2849551d 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IType.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -3,7 +3,7 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; -internal interface IType +internal interface IClass { /// /// The symbol of this type. diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs index 5975bd099..c8fc126d3 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs @@ -47,7 +47,7 @@ internal interface IModule /// /// The compiled types within this module. /// - public IReadOnlyDictionary Types { get; } + public IReadOnlyDictionary Types { get; } /// /// The procedure performing global initialization. diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs index 02ae2ca94..b8efd914b 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs @@ -27,7 +27,7 @@ internal interface IProcedure /// The type this procedure is defined in. /// When , this procedure is a free function. /// - public IType? DeclaringType { get; } + public IClass? DeclaringType { get; } /// /// The module this procedure is defined in. diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index e2c6d9d87..fc94ff21f 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -18,8 +18,8 @@ internal sealed class Module : IModule public IDictionary Submodules => this.submodules; IReadOnlyDictionary IModule.Submodules => this.submodules; - public IDictionary Types => this.types; - IReadOnlyDictionary IModule.Types => this.types; + public IDictionary Types => this.types; + IReadOnlyDictionary IModule.Types => this.types; public IReadOnlySet Fields => this.fields; @@ -38,7 +38,7 @@ internal sealed class Module : IModule private readonly HashSet fields = []; private readonly Dictionary procedures = []; private readonly Dictionary submodules = []; - private readonly Dictionary types = []; + private readonly Dictionary types = []; public Module(ModuleSymbol symbol, Assembly assembly, Module? Parent) { @@ -84,14 +84,14 @@ public Module DefineModule(ModuleSymbol moduleSymbol) return (Module)result; } - public Type DefineType(TypeSymbol typeSymbol) + public Class DefineType(TypeSymbol typeSymbol) { if (!this.types.TryGetValue(typeSymbol, out var result)) { - result = new Type(this, typeSymbol); + result = new Class(this, typeSymbol); this.types.Add(typeSymbol, result); } - return (Type)result; + return (Class)result; } public override string ToString() diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index bcfd843ca..04b048b42 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -17,8 +17,8 @@ internal sealed class Procedure : IProcedure public TypeSymbol? TypeSymbol => this.Symbol.Type; public Module DeclaringModule { get; } IModule IProcedure.DeclaringModule => this.DeclaringModule; - public Type? DeclaringType { get; } - IType? IProcedure.DeclaringType => this.DeclaringType; + public Class? DeclaringType { get; } + IClass? IProcedure.DeclaringType => this.DeclaringType; public Assembly Assembly => this.DeclaringModule.Assembly; IAssembly IProcedure.Assembly => this.Assembly; public BasicBlock Entry { get; } @@ -40,7 +40,7 @@ internal sealed class Procedure : IProcedure private readonly List locals = []; private readonly List registers = []; - public Procedure(Module declaringModule, Type? declaringType, FunctionSymbol symbol) + public Procedure(Module declaringModule, Class? declaringType, FunctionSymbol symbol) { this.DeclaringModule = declaringModule; this.DeclaringType = declaringType; diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index ed0f5a1f9..af71c2e64 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -186,7 +186,7 @@ public override FunctionSymbol GenericInstantiate(Symbol? containingSymbol, Immu public override FunctionSymbol GenericInstantiate(Symbol? containingSymbol, GenericContext context) => new FunctionInstanceSymbol(containingSymbol, this, context); - public override Api.Semantics.IFunctionSymbol ToApiSymbol() => new Api.Semantics.FunctionSymbol(this); + public override IFunctionSymbol ToApiSymbol() => new Api.Semantics.FunctionSymbol(this); public override void Accept(SymbolVisitor visitor) => visitor.VisitFunction(this); public override TResult Accept(SymbolVisitor visitor) => visitor.VisitFunction(this); diff --git a/src/Draco.Compiler/Internal/Symbols/Symbol.cs b/src/Draco.Compiler/Internal/Symbols/Symbol.cs index f66974a45..2e460c13f 100644 --- a/src/Draco.Compiler/Internal/Symbols/Symbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Symbol.cs @@ -158,7 +158,7 @@ public virtual string MetadataFullName /// /// The visibility of this symbol. /// - public virtual Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Internal; + public virtual Visibility Visibility => Visibility.Internal; /// /// The syntax declaring this symbol. @@ -323,11 +323,11 @@ private protected string GenericsToString() return string.Empty; } - private protected static Api.Semantics.Visibility GetVisibilityFromTokenKind(TokenKind? kind) => kind switch + private protected static Visibility GetVisibilityFromTokenKind(TokenKind? kind) => kind switch { - null => Api.Semantics.Visibility.Private, - TokenKind.KeywordInternal => Api.Semantics.Visibility.Internal, - TokenKind.KeywordPublic => Api.Semantics.Visibility.Public, + null => Visibility.Private, + TokenKind.KeywordInternal => Visibility.Internal, + TokenKind.KeywordPublic => Visibility.Public, _ => throw new InvalidOperationException($"illegal visibility modifier token {kind}"), }; diff --git a/src/Draco.Compiler/Internal/Symbols/TypeParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/TypeParameterSymbol.cs index f8396bcd8..b06687ab5 100644 --- a/src/Draco.Compiler/Internal/Symbols/TypeParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/TypeParameterSymbol.cs @@ -17,7 +17,7 @@ public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, GenericC ? type : this; - public override Api.Semantics.ITypeSymbol ToApiSymbol() => new Api.Semantics.TypeParameterSymbol(this); + public override ITypeSymbol ToApiSymbol() => new Api.Semantics.TypeParameterSymbol(this); public override string ToString() => this.Name; diff --git a/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs b/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs index ad99e1ecc..b0b782bac 100644 --- a/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs @@ -207,7 +207,7 @@ public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, GenericC return new TypeInstanceSymbol(containingSymbol, this, context); } - public override Api.Semantics.ITypeSymbol ToApiSymbol() => new Api.Semantics.TypeSymbol(this); + public override ITypeSymbol ToApiSymbol() => new Api.Semantics.TypeSymbol(this); public override void Accept(SymbolVisitor visitor) => visitor.VisitType(this); public override TResult Accept(SymbolVisitor visitor) => visitor.VisitType(this); diff --git a/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs b/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs index 834e86739..8c18c6c11 100644 --- a/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs +++ b/src/Draco.Compiler/Internal/Symbols/WellKnownTypes.cs @@ -204,7 +204,7 @@ public IEnumerable GetEnumEqualityMembers(TypeSymbol type) /// /// The reflected type to translate. /// The translated type symbol, or if it's not a translatable primitive type. - public TypeSymbol? TranslatePrimitive(System.Type type) + public TypeSymbol? TranslatePrimitive(Type type) { if (type == typeof(byte)) return this.SystemByte; if (type == typeof(ushort)) return this.SystemUInt16; @@ -225,7 +225,7 @@ public IEnumerable GetEnumEqualityMembers(TypeSymbol type) if (type == typeof(string)) return this.SystemString; if (type == typeof(object)) return this.SystemObject; - if (type == typeof(System.Type)) return this.SystemType; + if (type == typeof(Type)) return this.SystemType; return null; } diff --git a/src/Draco.DebugAdapter/DracoDebugAdapter.cs b/src/Draco.DebugAdapter/DracoDebugAdapter.cs index fa850877f..22eab28cb 100644 --- a/src/Draco.DebugAdapter/DracoDebugAdapter.cs +++ b/src/Draco.DebugAdapter/DracoDebugAdapter.cs @@ -219,7 +219,7 @@ public Task SetBreakpointsAsync(SetBreakpointsArguments return Task.FromResult(new SetBreakpointsResponse() { Breakpoints = args.Breakpoints? - .Select(bp => new Dap.Model.Breakpoint() + .Select(bp => new Breakpoint() { Verified = false, Id = this.translator.AllocateId(bp), @@ -235,11 +235,11 @@ public Task SetBreakpointsAsync(SetBreakpointsArguments }); } - private List SetBreakpointsImpl(SetBreakpointsArguments args) + private List SetBreakpointsImpl(SetBreakpointsArguments args) { if (this.debugger is null) throw new InvalidOperationException("cannot set up breakpoints without a running debugger"); - var result = new List(); + var result = new List(); var source = this.debugger.MainModule.SourceFiles .FirstOrDefault(s => PathEqualityComparer.Instance.Equals(s.Uri.AbsolutePath, args.Source.Path)); if (args.Breakpoints is not null && source is not null) diff --git a/src/Draco.SourceGeneration/Lsp/Translator.cs b/src/Draco.SourceGeneration/Lsp/Translator.cs index e536d63d5..699e5c4f1 100644 --- a/src/Draco.SourceGeneration/Lsp/Translator.cs +++ b/src/Draco.SourceGeneration/Lsp/Translator.cs @@ -24,7 +24,7 @@ internal sealed class Translator(Ts.MetaModel sourceModel) /// /// The name of the type. /// The reflected type. - public void AddBuiltinType(string name, System.Type type) => + public void AddBuiltinType(string name, Type type) => this.AddBuiltinType(name, type.FullName); /// From 0922f74ac59364a243beb49a808d7d093a037391 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 28 Oct 2024 00:48:21 +0100 Subject: [PATCH 042/109] using cleanup. --- src/Draco.Chr/Constraints/PropagationHistory.cs | 1 - src/Draco.Compiler.Cli/Program.cs | 1 - src/Draco.Compiler/Api/Semantics/SemanticModel.cs | 1 - .../Api/Syntax/Extensions/SyntaxNodeTraversalExtensions.cs | 1 - src/Draco.Compiler/Internal/Binding/Binder_Expression.cs | 2 -- src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs | 2 -- src/Draco.Compiler/Internal/Binding/Binder_Type.cs | 1 - src/Draco.Compiler/Internal/Binding/ClassBinder.cs | 3 --- .../Internal/Declarations/SingleModuleDeclaration.cs | 1 - .../Internal/OptimizingIr/Codegen/ClassCodegen.cs | 4 ---- src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs | 1 - .../Internal/Symbols/Error/ErrorThisParameterSymbol.cs | 3 --- .../Internal/Symbols/Metadata/AssemblyNameComparer.cs | 1 - .../Internal/Symbols/Metadata/MetadataSymbol.cs | 2 -- .../Internal/Symbols/Metadata/MetadataTypeSymbol.cs | 1 - .../Internal/Symbols/Source/SourceClassSymbol.cs | 2 -- .../Internal/Symbols/Source/SourceThisParameterSymbol.cs | 1 - .../Symbols/Synthetized/DefaultConstructorSymbol.cs | 7 ------- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 1 - src/Draco.Compiler/Internal/Syntax/Parser.cs | 2 -- src/Draco.Debugger/RuntimeValues/ObjectValue.cs | 1 - src/Draco.Fuzzing.Tui/Addons/ExportLcovAddon.cs | 1 - 22 files changed, 40 deletions(-) diff --git a/src/Draco.Chr/Constraints/PropagationHistory.cs b/src/Draco.Chr/Constraints/PropagationHistory.cs index ee089c387..b4faee3f7 100644 --- a/src/Draco.Chr/Constraints/PropagationHistory.cs +++ b/src/Draco.Chr/Constraints/PropagationHistory.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using Draco.Chr.Rules; diff --git a/src/Draco.Compiler.Cli/Program.cs b/src/Draco.Compiler.Cli/Program.cs index 68671e1cb..c31dae52a 100644 --- a/src/Draco.Compiler.Cli/Program.cs +++ b/src/Draco.Compiler.Cli/Program.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.CommandLine; -using System.CommandLine.Parsing; using System.IO; using System.Linq; using Draco.Compiler.Api; diff --git a/src/Draco.Compiler/Api/Semantics/SemanticModel.cs b/src/Draco.Compiler/Api/Semantics/SemanticModel.cs index e61398d13..7371f98fc 100644 --- a/src/Draco.Compiler/Api/Semantics/SemanticModel.cs +++ b/src/Draco.Compiler/Api/Semantics/SemanticModel.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/Draco.Compiler/Api/Syntax/Extensions/SyntaxNodeTraversalExtensions.cs b/src/Draco.Compiler/Api/Syntax/Extensions/SyntaxNodeTraversalExtensions.cs index f8dec1fd9..e85657c11 100644 --- a/src/Draco.Compiler/Api/Syntax/Extensions/SyntaxNodeTraversalExtensions.cs +++ b/src/Draco.Compiler/Api/Syntax/Extensions/SyntaxNodeTraversalExtensions.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index e5ce3ba7e..c8677c549 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Draco.Compiler.Api.Diagnostics; -using Draco.Compiler.Api.Semantics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding.Tasks; using Draco.Compiler.Internal.BoundTree; @@ -13,7 +12,6 @@ using Draco.Compiler.Internal.Solver.Tasks; using Draco.Compiler.Internal.Symbols; using Draco.Compiler.Internal.Symbols.Error; -using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Symbols.Syntax; using FieldSymbol = Draco.Compiler.Internal.Symbols.FieldSymbol; using FunctionGroupSymbol = Draco.Compiler.Internal.Symbols.Synthetized.FunctionGroupSymbol; diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs b/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs index ed4abe374..2ecafccde 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Lookup.cs @@ -2,13 +2,11 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Diagnostics; using Draco.Compiler.Internal.Solver; using Draco.Compiler.Internal.Solver.Tasks; using Draco.Compiler.Internal.Symbols; -using Draco.Compiler.Internal.Symbols.Error; using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.Binding; diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Type.cs b/src/Draco.Compiler/Internal/Binding/Binder_Type.cs index 7f13fa46f..80b4b3652 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Type.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Type.cs @@ -5,7 +5,6 @@ using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Diagnostics; using Draco.Compiler.Internal.Symbols; -using Draco.Compiler.Internal.Symbols.Error; namespace Draco.Compiler.Internal.Binding; diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs index eb0aa60d5..525d66959 100644 --- a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Symbols; -using Draco.Compiler.Internal.Symbols.Source; namespace Draco.Compiler.Internal.Binding; diff --git a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs index 5da878555..b3419e647 100644 --- a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using System.Linq; using Draco.Compiler.Api.Syntax; -using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.Declarations; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs index 5d3ae6088..a3fc5bb9c 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -1,7 +1,3 @@ -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Draco.Compiler.Api; using Draco.Compiler.Internal.BoundTree; using Draco.Compiler.Internal.Lowering; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs index c8fc126d3..2578d81c3 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using Draco.Compiler.Internal.Symbols; -using Draco.Compiler.Internal.Symbols.Source; namespace Draco.Compiler.Internal.OptimizingIr.Model; diff --git a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs index c7632c3d5..f38453e3f 100644 --- a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs @@ -1,6 +1,3 @@ -using Draco.Compiler.Internal.Binding; -using Draco.Compiler.Internal.Symbols.Source; - namespace Draco.Compiler.Internal.Symbols.Error; internal class ErrorThisParameterSymbol(TypeSymbol type, FunctionSymbol containingSymbol) : ParameterSymbol diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/AssemblyNameComparer.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/AssemblyNameComparer.cs index fc0d00be7..ac8164d8f 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/AssemblyNameComparer.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/AssemblyNameComparer.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Reflection; namespace Draco.Compiler.Internal.Symbols.Metadata; diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs index 7e0ca4a1b..9826b3e7d 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataSymbol.cs @@ -1,10 +1,8 @@ using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection; using System.Reflection.Metadata; -using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.Symbols.Metadata; diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs index e1381f9e2..c3cd96f10 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index ad6bffe4f..620153e99 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -3,8 +3,6 @@ using System.Collections.Immutable; using System.Diagnostics; using System.Linq; -using System.Threading; -using Draco.Compiler.Api; using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs index 6c090745b..5c11995ef 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Immutable; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs index 17f6ef483..f1446763e 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs @@ -1,11 +1,4 @@ -using System; -using System.Collections.Generic; using System.Collections.Immutable; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.BoundTree; using static Draco.Compiler.Internal.BoundTree.BoundTreeFactory; diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index c818e6f77..253f35089 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -3,7 +3,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; -using System.Linq; using System.Text; using Draco.Compiler.Api.Diagnostics; using Draco.Compiler.Api.Syntax; diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 7d9b594e7..542f1c5ec 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -1,10 +1,8 @@ using System; -using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using Draco.Compiler.Api.Diagnostics; -using Draco.Compiler.Api.Semantics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Diagnostics; diff --git a/src/Draco.Debugger/RuntimeValues/ObjectValue.cs b/src/Draco.Debugger/RuntimeValues/ObjectValue.cs index 49b96d1ed..220fee40f 100644 --- a/src/Draco.Debugger/RuntimeValues/ObjectValue.cs +++ b/src/Draco.Debugger/RuntimeValues/ObjectValue.cs @@ -4,7 +4,6 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using ClrDebug; -using Draco.Debugger; namespace Draco.Debugger.RuntimeValues; diff --git a/src/Draco.Fuzzing.Tui/Addons/ExportLcovAddon.cs b/src/Draco.Fuzzing.Tui/Addons/ExportLcovAddon.cs index cf6f11688..48f9f93d7 100644 --- a/src/Draco.Fuzzing.Tui/Addons/ExportLcovAddon.cs +++ b/src/Draco.Fuzzing.Tui/Addons/ExportLcovAddon.cs @@ -1,4 +1,3 @@ -using System; using System.IO; using System.Linq; using Draco.Coverage; From 5fe55adf57a7b8681575f23ad63b5f89a24323be Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 28 Oct 2024 01:21:18 +0100 Subject: [PATCH 043/109] some pr feedback. --- .../Semantics/AttributeTests.cs | 4 +- .../Semantics/ControlFlowGraphTests.cs | 18 ++--- .../Semantics/DefiniteAssignmentTests.cs | 8 +- .../Semantics/LocalFunctionsTests.cs | 12 +-- .../Semantics/OverloadingTests.cs | 12 +-- .../Semantics/ReturnsOnAllPathsTests.cs | 8 +- .../Semantics/SingleAssignmentTests.cs | 6 +- .../Semantics/SymbolResolutionTests.cs | 26 +++--- .../Semantics/TypeCheckingTests.cs | 80 +++++++++---------- .../Syntax/ParserTests.cs | 22 ++--- .../CodeCompletion/CompletionService.cs | 2 +- .../Api/Syntax/SyntaxFactory.cs | 26 +++--- src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs | 2 +- .../Api/Syntax/SyntaxHighlighter.cs | 2 +- .../Internal/Binding/BinderFacts.cs | 2 +- .../Internal/Binding/Binder_Expression.cs | 34 +++----- .../Internal/Binding/LocalBinder.cs | 2 +- .../Internal/Declarations/ClassDeclaration.cs | 8 +- .../Declarations/FunctionDeclaration.cs | 8 +- .../Declarations/GlobalDeclaration.cs | 8 +- .../Declarations/SingleModuleDeclaration.cs | 8 +- .../Symbols/Source/SourceParameterSymbol.cs | 4 +- .../Symbols/Syntax/SyntaxFunctionSymbol.cs | 2 +- src/Draco.Compiler/Internal/Syntax/Parser.cs | 6 +- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 8 +- .../Capabilities/Rename.cs | 2 +- 26 files changed, 141 insertions(+), 179 deletions(-) diff --git a/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs b/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs index b2c8cfbd5..aee64a4fd 100644 --- a/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs @@ -103,7 +103,7 @@ public void AttributeIsWrittenIntoMetadata() FunctionDeclaration( [Attribute(NameType("ObsoleteAttribute"), StringExpression("do not use this function"))], "foo", - ParameterList(Parameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), + ParameterList(NormalParameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), null, BlockFunctionBody()))); @@ -132,7 +132,7 @@ public void AttributeReferencesTheSymbol() FunctionDeclaration( [Attribute(NameType("ObsoleteAttribute"), StringExpression("do not use this function"))], "foo", - ParameterList(Parameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), + ParameterList(NormalParameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), null, BlockFunctionBody()))); diff --git a/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs b/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs index dcdcdd0c5..c1fb579f7 100644 --- a/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs @@ -83,7 +83,7 @@ public async Task IfElse() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(IfExpression( @@ -149,7 +149,7 @@ public async Task EarlyReturn() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(CallExpression(NameExpression("bar"))), @@ -181,7 +181,7 @@ public async Task ConditionalGotoInAssignment() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(VariableDeclaration(true, "x", null, IfExpression( @@ -211,14 +211,14 @@ public async Task ForLoop() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(Parameter("s", GenericType(NameType("Array"), NameType("int32")))), + ParameterList(NormalParameter("s", GenericType(NameType("Array"), NameType("int32")))), null, BlockFunctionBody( ExpressionStatement(ForExpression( "i", NameExpression("s"), CallExpression(NameExpression("bar"), NameExpression("i")))))), - FunctionDeclaration("bar", ParameterList(Parameter("x", NameType("int32"))), null, BlockFunctionBody()))); + FunctionDeclaration("bar", ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody()))); // Act var cfg = FunctionToCfg(program); @@ -243,10 +243,10 @@ public async Task ChainedComparison() FunctionDeclaration( "foo", ParameterList( - Parameter("a", NameType("int32")), - Parameter("b", NameType("int32")), - Parameter("c", NameType("int32")), - Parameter("d", NameType("int32"))), + NormalParameter("a", NameType("int32")), + NormalParameter("b", NameType("int32")), + NormalParameter("c", NameType("int32")), + NormalParameter("d", NameType("int32"))), null, InlineFunctionBody(RelationalExpression( BlockExpression([ExpressionStatement(CallExpression(NameExpression("bar")))], NameExpression("a")), diff --git a/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs b/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs index 27999f55c..4192c5295 100644 --- a/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/DefiniteAssignmentTests.cs @@ -69,7 +69,7 @@ public void UseOfConditionallyAssignedVariable() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), @@ -100,7 +100,7 @@ public void UseOfConditionallyAssignedVariableOnBothBranches() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"))), @@ -130,7 +130,7 @@ public void JumpingMidAssignment() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(VariableDeclaration(true, "x", NameType("int32"), IfExpression( @@ -189,7 +189,7 @@ public void UseVariableAssignedLater() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(WhileExpression( diff --git a/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs b/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs index 2339fb4f3..3958fe655 100644 --- a/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/LocalFunctionsTests.cs @@ -24,13 +24,13 @@ public void ParameterRedefinitionError() BlockFunctionBody(DeclarationStatement(FunctionDeclaration( "bar", ParameterList( - Parameter("x", NameType("int32")), - Parameter("x", NameType("int32"))), + NormalParameter("x", NameType("int32")), + NormalParameter("x", NameType("int32"))), null, BlockFunctionBody())))))); - var x1Decl = tree.GetNode(0); - var x2Decl = tree.GetNode(1); + var x1Decl = tree.GetNode(0); + var x2Decl = tree.GetNode(1); // Act var compilation = CreateCompilation(tree); @@ -190,7 +190,7 @@ public void LocalFunctionContributesToOverloading() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( name: "foo", - parameters: ParameterList(Parameter("x", NameType("int32"))), + parameters: ParameterList(NormalParameter("x", NameType("int32"))), returnType: null, body: BlockFunctionBody()), FunctionDeclaration( @@ -200,7 +200,7 @@ public void LocalFunctionContributesToOverloading() body: BlockFunctionBody( DeclarationStatement(FunctionDeclaration( name: "foo", - parameters: ParameterList(Parameter("x", NameType("string"))), + parameters: ParameterList(NormalParameter("x", NameType("string"))), returnType: null, body: BlockFunctionBody())), ExpressionStatement(CallExpression(NameExpression("foo"), LiteralExpression(0))), diff --git a/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs b/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs index f8b21befe..7987b5067 100644 --- a/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs @@ -18,34 +18,34 @@ public sealed class OverloadingTests private static IEnumerable GetGenericListOverloads() => [ FunctionDeclaration( "foo", - ParameterList(Parameter("l", GenericType(NameType("List"), NameType("int32")))), + ParameterList(NormalParameter("l", GenericType(NameType("List"), NameType("int32")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(Parameter("l", GenericType(NameType("List"), NameType("string")))), + ParameterList(NormalParameter("l", GenericType(NameType("List"), NameType("string")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("l", GenericType(NameType("List"), NameType("T")))), + ParameterList(NormalParameter("l", GenericType(NameType("List"), NameType("T")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(Parameter("l", GenericType(NameType("IEnumerable"), NameType("int32")))), + ParameterList(NormalParameter("l", GenericType(NameType("IEnumerable"), NameType("int32")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(Parameter("l", GenericType(NameType("IEnumerable"), NameType("string")))), + ParameterList(NormalParameter("l", GenericType(NameType("IEnumerable"), NameType("string")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("l", GenericType(NameType("IEnumerable"), NameType("T")))), + ParameterList(NormalParameter("l", GenericType(NameType("IEnumerable"), NameType("T")))), null, BlockFunctionBody()), ]; diff --git a/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs b/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs index 0c65af6c7..efc977dcd 100644 --- a/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs @@ -98,7 +98,7 @@ public void NonUnitMethodReturnsConditionally() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(IfExpression( @@ -124,7 +124,7 @@ public void NonUnitMethodReturnsConditionallyOnBothBranches() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(IfExpression( @@ -151,7 +151,7 @@ public void NonUnitMethodReturnsConditionallyButThenUnconditionally() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(IfExpression( @@ -177,7 +177,7 @@ public void NonUnitMethodReturnsInConditionalLoop() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(WhileExpression( diff --git a/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs b/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs index d3669c9e9..c4064fea9 100644 --- a/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SingleAssignmentTests.cs @@ -66,7 +66,7 @@ public void AssignImmutableInMutuallyExclusiveBranches() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))), @@ -95,7 +95,7 @@ public void ConditionallyAndThenUnconditionallyAssignImmutable() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))), @@ -124,7 +124,7 @@ public void AssignImmutableInLoop() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("b", NameType("bool"))), + ParameterList(NormalParameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(ImmutableVariableDeclaration(true, "x", NameType("int32"))), diff --git a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs index f9479a94b..9711e1959 100644 --- a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs @@ -40,7 +40,7 @@ public void BasicScopeTree() var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", ParameterList( - Parameter("n", NameType("int32"))), + NormalParameter("n", NameType("int32"))), null, BlockFunctionBody( DeclarationStatement(VariableDeclaration(true, "x1")), @@ -53,7 +53,7 @@ public void BasicScopeTree() ExpressionStatement(BlockExpression(DeclarationStatement(VariableDeclaration(true, "x6")))))))))); var foo = tree.GetNode(); - var n = tree.GetNode(); + var n = tree.GetNode(); var x1 = tree.GetNode(0); var x2 = tree.GetNode(1); var x3 = tree.GetNode(2); @@ -327,13 +327,13 @@ public void ParameterRedefinitionError() var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", ParameterList( - Parameter("x", NameType("int32")), - Parameter("x", NameType("int32"))), + NormalParameter("x", NameType("int32")), + NormalParameter("x", NameType("int32"))), null, BlockFunctionBody()))); - var x1Decl = tree.GetNode(0); - var x2Decl = tree.GetNode(1); + var x1Decl = tree.GetNode(0); + var x2Decl = tree.GetNode(1); // Act var compilation = CreateCompilation(tree); @@ -361,14 +361,14 @@ public void RedefinedParameterReference() var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", ParameterList( - Parameter("x", NameType("int32")), - Parameter("x", NameType("int32"))), + NormalParameter("x", NameType("int32")), + NormalParameter("x", NameType("int32"))), null, BlockFunctionBody( DeclarationStatement(VariableDeclaration(true, "y", null, NameExpression("x"))))))); - var x1Decl = tree.GetNode(0); - var x2Decl = tree.GetNode(1); + var x1Decl = tree.GetNode(0); + var x2Decl = tree.GetNode(1); var xRef = tree.GetNode(0); // Act @@ -418,7 +418,7 @@ public void FuncOverloadsGlobalVar() VariableDeclaration(true, "b", NameType("int32")), FunctionDeclaration( "b", - ParameterList(Parameter("b", NameType("int32"))), + ParameterList(NormalParameter("b", NameType("int32"))), NameType("int32"), InlineFunctionBody(NameExpression("b"))))); @@ -1664,7 +1664,7 @@ public void UndefinedTypeInParameterType() // Arrange var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("unknown"))), + ParameterList(NormalParameter("x", NameType("unknown"))), null, BlockFunctionBody()))); @@ -3246,7 +3246,7 @@ public void GenericFunction() var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("T"))), + ParameterList(NormalParameter("x", NameType("T"))), NameType("T"), InlineFunctionBody(NameExpression("x"))))); diff --git a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs index 6583a3585..761246072 100644 --- a/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/TypeCheckingTests.cs @@ -655,7 +655,7 @@ public void OneVisibleAndOneNotVisibleOverloadImported() FunctionDeclaration( Api.Semantics.Visibility.Internal, "foo", - ParameterList(Parameter("x", NameType("string"))), + ParameterList(NormalParameter("x", NameType("string"))), NameType("int32"), InlineFunctionBody(LiteralExpression(0)))), ToPath("Tests", "FooModule", "foo.draco")); @@ -702,7 +702,7 @@ public void OneVisibleAndOneNotVisibleOverloadFullyQualified() FunctionDeclaration( Api.Semantics.Visibility.Internal, "foo", - ParameterList(Parameter("x", NameType("string"))), + ParameterList(NormalParameter("x", NameType("string"))), NameType("int32"), InlineFunctionBody(LiteralExpression(0)))), ToPath("Tests", "FooModule", "foo.draco")); @@ -736,12 +736,12 @@ public void OkOverloading() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("bool"))), + ParameterList(NormalParameter("x", NameType("bool"))), null, BlockFunctionBody()), FunctionDeclaration( @@ -788,12 +788,12 @@ public void OkNestedOverloading() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody( DeclarationStatement(FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("bool"))), + ParameterList(NormalParameter("x", NameType("bool"))), null, BlockFunctionBody())), ExpressionStatement(CallExpression(NameExpression("foo"), LiteralExpression(0))), @@ -837,12 +837,12 @@ public void NestedOverloadNotVisibleFromOutside() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody( DeclarationStatement(FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("bool"))), + ParameterList(NormalParameter("x", NameType("bool"))), null, BlockFunctionBody())))), FunctionDeclaration( @@ -888,12 +888,12 @@ public void IllegalOverloading() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody()))); @@ -919,13 +919,13 @@ public void IllegalOverloadingWithGenerics() FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("int32")), Parameter("y", NameType("T"))), + ParameterList(NormalParameter("x", NameType("int32")), NormalParameter("y", NameType("T"))), null, BlockFunctionBody()), FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("int32")), Parameter("y", NameType("T"))), + ParameterList(NormalParameter("x", NameType("int32")), NormalParameter("y", NameType("T"))), null, BlockFunctionBody()))); @@ -951,12 +951,12 @@ public void IllegalNestedOverloading() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody( DeclarationStatement(FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody())))))); @@ -992,12 +992,12 @@ public void NestedMatchingLocalOverloads() var tree = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody( DeclarationStatement(FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("bool"))), + ParameterList(NormalParameter("x", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(CallExpression(NameExpression("foo"), LiteralExpression(0))), @@ -1009,7 +1009,7 @@ public void NestedMatchingLocalOverloads() BlockFunctionBody( DeclarationStatement(FunctionDeclaration( "foo", - ParameterList(Parameter("x", NameType("bool"))), + ParameterList(NormalParameter("x", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(CallExpression(NameExpression("foo"), LiteralExpression(0))), @@ -1191,7 +1191,7 @@ public void ExplicitGenericFunction() FunctionDeclaration( "identity", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("T"))), + ParameterList(NormalParameter("x", NameType("T"))), NameType("T"), InlineFunctionBody(NameExpression("x"))), FunctionDeclaration( @@ -1269,7 +1269,7 @@ public void ExplicitGenericFunctionWithWrongNumberOfArgs() FunctionDeclaration( "identity", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("T"))), + ParameterList(NormalParameter("x", NameType("T"))), NameType("T"), InlineFunctionBody(NameExpression("x"))), FunctionDeclaration( @@ -1362,7 +1362,7 @@ public void InferGenericFunctionParameterTypeFromUse() FunctionDeclaration( "identity", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("T"))), + ParameterList(NormalParameter("x", NameType("T"))), NameType("T"), InlineFunctionBody(NameExpression("x"))), FunctionDeclaration( @@ -1490,12 +1490,12 @@ public void ExactMatchOverloadPriorityOverGeneric() FunctionDeclaration( "identity", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("T"))), + ParameterList(NormalParameter("x", NameType("T"))), NameType("T"), InlineFunctionBody(NameExpression("x"))), FunctionDeclaration( "identity", - ParameterList(Parameter("x", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("int32"))), NameType("int32"), InlineFunctionBody(NameExpression("x"))), FunctionDeclaration( @@ -1551,13 +1551,13 @@ public void AmbiguousOverload() FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("T")), Parameter("y", NameType("int32"))), + ParameterList(NormalParameter("x", NameType("T")), NormalParameter("y", NameType("int32"))), null, BlockFunctionBody()), FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(Parameter("x", NameType("int32")), Parameter("y", NameType("T"))), + ParameterList(NormalParameter("x", NameType("int32")), NormalParameter("y", NameType("T"))), null, BlockFunctionBody()), FunctionDeclaration( @@ -1595,14 +1595,14 @@ public void VariadicOverloadPriority() FunctionDeclaration( "bar", ParameterList( - Parameter("s", NameType("string")), - Parameter("x", NameType("int32"))), + NormalParameter("s", NameType("string")), + NormalParameter("x", NameType("int32"))), NameType("int32"), InlineFunctionBody(LiteralExpression(0))), FunctionDeclaration( "bar", ParameterList( - Parameter("s", NameType("string")), + NormalParameter("s", NameType("string")), VariadicParameter("x", GenericType(NameType("Array"), NameType("int32")))), NameType("int32"), InlineFunctionBody(LiteralExpression(0))), @@ -1666,15 +1666,15 @@ public void GenericVariadicOverloadPriority() "bar", GenericParameterList(GenericParameter("T")), ParameterList( - Parameter("s", NameType("string")), - Parameter("x", NameType("T"))), + NormalParameter("s", NameType("string")), + NormalParameter("x", NameType("T"))), NameType("int32"), InlineFunctionBody(LiteralExpression(0))), FunctionDeclaration( "bar", GenericParameterList(GenericParameter("T")), ParameterList( - Parameter("s", NameType("string")), + NormalParameter("s", NameType("string")), VariadicParameter("x", GenericType(NameType("Array"), NameType("T")))), NameType("int32"), InlineFunctionBody(LiteralExpression(0))), @@ -1732,8 +1732,8 @@ public void InferredGenericsMismatch() "foo", GenericParameterList(GenericParameter("T")), ParameterList( - Parameter("x", NameType("T")), - Parameter("y", NameType("T"))), + NormalParameter("x", NameType("T")), + NormalParameter("y", NameType("T"))), null, BlockFunctionBody()), FunctionDeclaration( @@ -1886,7 +1886,7 @@ public void PassDerivedTypeToBaseTypeParameter() ExpressionStatement(CallExpression(NameExpression("bar"), CallExpression(NameExpression("Random")))))), FunctionDeclaration( "bar", - ParameterList(Parameter("x", NameType("Object"))), + ParameterList(NormalParameter("x", NameType("Object"))), null, BlockFunctionBody()))); @@ -1922,7 +1922,7 @@ public void PassBaseTypeToDerivedTypeParameter() ExpressionStatement(CallExpression(NameExpression("bar"), CallExpression(NameExpression("Object")))))), FunctionDeclaration( "bar", - ParameterList(Parameter("x", NameType("String"))), + ParameterList(NormalParameter("x", NameType("String"))), null, BlockFunctionBody()))); @@ -1961,12 +1961,12 @@ public void BaseTypeArgumentOverloading() ExpressionStatement(CallExpression(NameExpression("bar"), CallExpression(NameExpression("Object")))))), FunctionDeclaration( "bar", - ParameterList(Parameter("x", NameType("Object"))), + ParameterList(NormalParameter("x", NameType("Object"))), null, BlockFunctionBody()), FunctionDeclaration( "bar", - ParameterList(Parameter("x", NameType("Random"))), + ParameterList(NormalParameter("x", NameType("Random"))), null, BlockFunctionBody()))); @@ -2019,9 +2019,9 @@ public void BaseTypeGenericsCall() "bar", GenericParameterList(GenericParameter("T")), ParameterList( - Parameter("x", NameType("T")), - Parameter("y", NameType("T")), - Parameter("z", NameType("T"))), + NormalParameter("x", NameType("T")), + NormalParameter("y", NameType("T")), + NormalParameter("z", NameType("T"))), null, BlockFunctionBody()))); @@ -2417,7 +2417,7 @@ public void GenericTypeNotInstantiatedInTypeContextIsAnError() var main = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(Parameter("a", NameType("Array2D"))), + ParameterList(NormalParameter("a", NameType("Array2D"))), null, BlockFunctionBody()))); diff --git a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs index 08f6e8ea5..f44cac6fc 100644 --- a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs +++ b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs @@ -100,7 +100,7 @@ func main() { this.T(TokenKind.Identifier); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -170,7 +170,7 @@ func main() { this.T(TokenKind.Identifier); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -199,7 +199,7 @@ func main() { this.T(TokenKind.Identifier); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -247,7 +247,7 @@ func foo() { } this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); @@ -1988,9 +1988,9 @@ func foo(@Attr2("this is a parameter") x: int32) {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "foo"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); { - this.N(); + this.N(); { this.N>(); this.N(); @@ -2051,7 +2051,7 @@ public func bar() {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "foo"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); { @@ -2064,7 +2064,7 @@ public func bar() {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "bar"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); { @@ -2096,7 +2096,7 @@ public void TestEmptyGenericParameterList() this.T(TokenKind.GreaterThan); } this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); this.T(TokenKind.ParenClose); this.N(); { @@ -2119,9 +2119,9 @@ func foo(x: List<>) {} this.T(TokenKind.KeywordFunc); this.T(TokenKind.Identifier, "foo"); this.T(TokenKind.ParenOpen); - this.N>(); + this.N>(); { - this.N(); + this.N(); { this.T(TokenKind.Identifier, "x"); this.T(TokenKind.Colon); diff --git a/src/Draco.Compiler/Api/Services/CodeCompletion/CompletionService.cs b/src/Draco.Compiler/Api/Services/CodeCompletion/CompletionService.cs index 318d3c1f2..38b9c3ed1 100644 --- a/src/Draco.Compiler/Api/Services/CodeCompletion/CompletionService.cs +++ b/src/Draco.Compiler/Api/Services/CodeCompletion/CompletionService.cs @@ -87,7 +87,7 @@ public ImmutableArray GetCompletions(SemanticModel semanticModel // Type expression NameTypeSyntax => CompletionContext.Type, // Parameter name declaration - ParameterSyntax => CompletionContext.None, + NormalParameterSyntax => CompletionContext.None, // Global declaration UnexpectedDeclarationSyntax => CompletionContext.Declaration, // Declaring identifier diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index a0a11b340..321b3935c 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -93,16 +93,16 @@ public static SeparatedSyntaxList SeparatedSyntaxList(SyntaxToken public static SeparatedSyntaxList SeparatedSyntaxList(SyntaxToken separator, params TNode[] elements) where TNode : SyntaxNode => SeparatedSyntaxList(separator, elements.AsEnumerable()); - public static SeparatedSyntaxList ParameterList(IEnumerable parameters) => + public static SeparatedSyntaxList ParameterList(IEnumerable parameters) => SeparatedSyntaxList(Comma, parameters); - public static SeparatedSyntaxList ParameterList(params ParameterSyntaxBase[] parameters) => + public static SeparatedSyntaxList ParameterList(params ParameterSyntax[] parameters) => SeparatedSyntaxList(Comma, parameters); - public static ParameterSyntax Parameter(string name, TypeSyntax type) => - Parameter([], name, type); - public static ParameterSyntax Parameter(IEnumerable attributes, string name, TypeSyntax type) => - Parameter(SyntaxList(attributes), null, Identifier(name), Colon, type); - public static ParameterSyntax VariadicParameter(string name, TypeSyntax type) => - Parameter(SyntaxList(), Ellipsis, Identifier(name), Colon, type); + public static NormalParameterSyntax NormalParameter(string name, TypeSyntax type) => + NormalParameter([], name, type); + public static NormalParameterSyntax NormalParameter(IEnumerable attributes, string name, TypeSyntax type) => + NormalParameter(SyntaxList(attributes), null, Identifier(name), Colon, type); + public static NormalParameterSyntax VariadicParameter(string name, TypeSyntax type) => + NormalParameter(SyntaxList(), Ellipsis, Identifier(name), Colon, type); public static GenericParameterListSyntax GenericParameterList(IEnumerable parameters) => GenericParameterList(SeparatedSyntaxList(Comma, parameters)); @@ -123,7 +123,7 @@ public static ImportDeclarationSyntax ImportDeclaration(string root, params stri public static FunctionDeclarationSyntax FunctionDeclaration( string name, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration([], Semantics.Visibility.Private, name, null, parameters, returnType, body); @@ -131,7 +131,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( IEnumerable attributes, string name, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration(attributes, Semantics.Visibility.Private, name, null, parameters, returnType, body); @@ -139,7 +139,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( Visibility visibility, string name, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration([], visibility, name, null, parameters, returnType, body); @@ -147,7 +147,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( public static FunctionDeclarationSyntax FunctionDeclaration( string name, GenericParameterListSyntax? generics, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration([], Semantics.Visibility.Private, name, generics, parameters, returnType, body); @@ -157,7 +157,7 @@ public static FunctionDeclarationSyntax FunctionDeclaration( Visibility visibility, string name, GenericParameterListSyntax? generics, - SeparatedSyntaxList parameters, + SeparatedSyntaxList parameters, TypeSyntax? returnType, FunctionBodySyntax body) => FunctionDeclaration( attributes, diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs index 078baffe7..3661d6972 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFacts.cs @@ -157,7 +157,7 @@ _ when IsMissing(node) => false, ModuleDeclarationSyntax md => !IsMissing(md.CloseBrace), ImportDeclarationSyntax id => !IsMissing(id.Semicolon), FunctionDeclarationSyntax fd => IsCompleteEntry(fd.Body), - ParameterSyntax p => IsCompleteEntry(p.Type), + NormalParameterSyntax p => IsCompleteEntry(p.Type), BlockFunctionBodySyntax bfb => !IsMissing(bfb.CloseBrace), InlineFunctionBodySyntax ifb => !IsMissing(ifb.Semicolon), LabelDeclarationSyntax ld => !IsMissing(ld.Colon), diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxHighlighter.cs b/src/Draco.Compiler/Api/Syntax/SyntaxHighlighter.cs index 6e50d7956..2e49eea72 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxHighlighter.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxHighlighter.cs @@ -140,7 +140,7 @@ or TokenKind.BracketOpen private static IEnumerable Identifier(SyntaxToken token, SemanticModel? semanticModel) { // Make a guess based on syntax - if (token.Parent is ParameterSyntax param && param.Name.Equals(token)) + if (token.Parent is NormalParameterSyntax param && param.Name.Equals(token)) { return Fragment(token, SyntaxColoring.ParameterName); } diff --git a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs index 0108c1ace..c8f9d9ba9 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderFacts.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderFacts.cs @@ -133,7 +133,7 @@ or ForExpressionSyntax public static bool DefinesSymbol(SyntaxNode node) => node is FunctionDeclarationSyntax or VariableDeclarationSyntax - or ParameterSyntax + or NormalParameterSyntax or LabelDeclarationSyntax or ClassDeclarationSyntax; diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index c8677c549..52e414482 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -13,15 +13,7 @@ using Draco.Compiler.Internal.Symbols; using Draco.Compiler.Internal.Symbols.Error; using Draco.Compiler.Internal.Symbols.Syntax; -using FieldSymbol = Draco.Compiler.Internal.Symbols.FieldSymbol; -using FunctionGroupSymbol = Draco.Compiler.Internal.Symbols.Synthetized.FunctionGroupSymbol; -using FunctionSymbol = Draco.Compiler.Internal.Symbols.FunctionSymbol; -using LabelSymbol = Draco.Compiler.Internal.Symbols.LabelSymbol; -using LocalSymbol = Draco.Compiler.Internal.Symbols.LocalSymbol; -using ModuleSymbol = Draco.Compiler.Internal.Symbols.ModuleSymbol; -using ParameterSymbol = Draco.Compiler.Internal.Symbols.ParameterSymbol; -using PropertySymbol = Draco.Compiler.Internal.Symbols.PropertySymbol; -using TypeSymbol = Draco.Compiler.Internal.Symbols.TypeSymbol; +using Draco.Compiler.Internal.Symbols.Synthetized; namespace Draco.Compiler.Internal.Binding; @@ -74,7 +66,7 @@ private async BindingTask BindExpressionToValueProducingExpress UnaryExpressionSyntax ury => this.BindUnaryExpression(ury, constraints, diagnostics), BinaryExpressionSyntax bin => this.BindBinaryExpression(bin, constraints, diagnostics), RelationalExpressionSyntax rel => this.BindRelationalExpression(rel, constraints, diagnostics), - MemberExpressionSyntax maccess => this.BindMemberExpression(maccess, constraints, diagnostics), + MemberExpressionSyntax mem => this.BindMemberExpression(mem, constraints, diagnostics), GenericExpressionSyntax gen => this.BindGenericExpression(gen, constraints, diagnostics), IndexExpressionSyntax index => this.BindIndexExpression(index, constraints, diagnostics), ThisExpressionSyntax @this => this.BindThisExpression(@this, constraints, diagnostics), @@ -718,10 +710,7 @@ private async BindingTask BindIndexExpression(IndexExpressionSy // Array getter return new BoundArrayAccessExpression(syntax, receiver, await BindingTask.WhenAll(argsTask)); } - else - { - return new BoundIndexGetExpression(syntax, receiver, indexer, await BindingTask.WhenAll(argsTask)); - } + return new BoundIndexGetExpression(syntax, receiver, indexer, await BindingTask.WhenAll(argsTask)); } private BindingTask BindThisExpression(ThisExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) @@ -871,16 +860,13 @@ private BindingTask WrapFunctions( return BindingTask.FromResult( new BoundDelegateCreationExpression(syntax, receiver, functions[0], delegateCtor)); } - else - { - // TODO: We should construct some constraints to resolve which one - // For now we report an error to not crash tools - diagnostics.Add(Diagnostic.Create( - template: TypeCheckingErrors.IllegalExpression, - location: syntax.Location)); - return BindingTask.FromResult( - new BoundReferenceErrorExpression(syntax, WellKnownTypes.ErrorType)); - } + // TODO: We should construct some constraints to resolve which one + // For now we report an error to not crash tools + diagnostics.Add(Diagnostic.Create( + template: TypeCheckingErrors.IllegalExpression, + location: syntax.Location)); + return BindingTask.FromResult( + new BoundReferenceErrorExpression(syntax, WellKnownTypes.ErrorType)); } } diff --git a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs index 57c99d461..ef569501b 100644 --- a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs @@ -168,7 +168,7 @@ private void Build() private Symbol? BuildSymbol(SyntaxNode syntax, int localCount) => syntax switch { FunctionDeclarationSyntax function => new SourceFunctionSymbol(this.ContainingSymbol, function), - ParameterSyntax parameter => new SourceParameterSymbol((FunctionSymbol)this.ContainingSymbol, parameter), + NormalParameterSyntax parameter => new SourceParameterSymbol((FunctionSymbol)this.ContainingSymbol, parameter), VariableDeclarationSyntax variable => variable.FieldKeyword is null ? new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable) : new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, variable), diff --git a/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs index a1e43c269..93f099509 100644 --- a/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/ClassDeclaration.cs @@ -21,13 +21,7 @@ internal sealed class ClassDeclaration(ClassDeclarationSyntax syntax) : Declarat InterlockedUtils.InitializeDefault(ref this.children, this.BuildChildren); private ImmutableArray children; - public override IEnumerable DeclaringSyntaxes - { - get - { - yield return this.Syntax; - } - } + public override IEnumerable DeclaringSyntaxes => [this.Syntax]; private ImmutableArray BuildChildren() { diff --git a/src/Draco.Compiler/Internal/Declarations/FunctionDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/FunctionDeclaration.cs index 6ffc27b45..d1904330f 100644 --- a/src/Draco.Compiler/Internal/Declarations/FunctionDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/FunctionDeclaration.cs @@ -17,11 +17,5 @@ internal sealed class FunctionDeclaration(FunctionDeclarationSyntax syntax) public override ImmutableArray Children => []; - public override IEnumerable DeclaringSyntaxes - { - get - { - yield return this.Syntax; - } - } + public override IEnumerable DeclaringSyntaxes => [this.Syntax]; } diff --git a/src/Draco.Compiler/Internal/Declarations/GlobalDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/GlobalDeclaration.cs index 9fcfe7dfb..fef7bfdba 100644 --- a/src/Draco.Compiler/Internal/Declarations/GlobalDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/GlobalDeclaration.cs @@ -17,11 +17,5 @@ internal sealed class GlobalDeclaration(VariableDeclarationSyntax syntax) public override ImmutableArray Children => []; - public override IEnumerable DeclaringSyntaxes - { - get - { - yield return this.Syntax; - } - } + public override IEnumerable DeclaringSyntaxes => [this.Syntax]; } diff --git a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs index b3419e647..c2420a858 100644 --- a/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs +++ b/src/Draco.Compiler/Internal/Declarations/SingleModuleDeclaration.cs @@ -27,13 +27,7 @@ internal sealed class SingleModuleDeclaration(string name, SplitPath path, Conta InterlockedUtils.InitializeDefault(ref this.children, this.BuildChildren); private ImmutableArray children; - public override IEnumerable DeclaringSyntaxes - { - get - { - yield return this.Syntax; - } - } + public override IEnumerable DeclaringSyntaxes => [this.Syntax]; private ImmutableArray BuildChildren() => this.Syntax.Declarations.Select(this.BuildChild).OfType().ToImmutableArray(); diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceParameterSymbol.cs index ca507aa63..f56897587 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceParameterSymbol.cs @@ -12,7 +12,7 @@ namespace Draco.Compiler.Internal.Symbols.Source; /// internal sealed class SourceParameterSymbol( FunctionSymbol containingSymbol, - ParameterSyntax syntax) : ParameterSymbol, ISourceSymbol + NormalParameterSyntax syntax) : ParameterSymbol, ISourceSymbol { public override ImmutableArray Attributes => this.BindAttributesIfNeeded(this.DeclaringCompilation!); private ImmutableArray attributes; @@ -24,7 +24,7 @@ internal sealed class SourceParameterSymbol( public override bool IsVariadic => this.DeclaringSyntax.Variadic is not null; public override string Name => this.DeclaringSyntax.Name.Text; - public override ParameterSyntax DeclaringSyntax { get; } = syntax; + public override NormalParameterSyntax DeclaringSyntax { get; } = syntax; public void Bind(IBinderProvider binderProvider) { diff --git a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs index 77f3e9a2a..2ba7d9626 100644 --- a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs @@ -130,7 +130,7 @@ private ImmutableArray BindParameters(IBinderProvider binderPro parameters.Add(asSymbol); continue; } - var parameterSyntax = (ParameterSyntax)syntax; + var parameterSyntax = (NormalParameterSyntax)syntax; var parameterName = parameterSyntax.Name.Text; diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 542f1c5ec..e58a88900 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -808,8 +808,8 @@ private DeclarationSyntax ParseLabelDeclaration( /// /// Parses a function parameter. /// - /// The parsed . - private ParameterSyntaxBase ParseParameter() + /// The parsed . + private ParameterSyntax ParseParameter() { var attributes = this.ParseAttributeList(); if (this.Matches(TokenKind.KeywordThis, out var thisKeyWord)) @@ -825,7 +825,7 @@ private ParameterSyntaxBase ParseParameter() var name = this.Expect(TokenKind.Identifier); var colon = this.Expect(TokenKind.Colon); var type = this.ParseType(); - return new ParameterSyntax(attributes, variadic, name, colon, type); + return new NormalParameterSyntax(attributes, variadic, name, colon, type); } /// diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index df71aa130..bf5a7dade 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -481,7 +481,7 @@ - + The parameters this function declares. @@ -505,13 +505,13 @@ - + A single parameter in a function parameter list. - + The this parameter at the first place in a parameter list. @@ -524,7 +524,7 @@ - + A single parameter in a function parameter list. diff --git a/src/Draco.LanguageServer/Capabilities/Rename.cs b/src/Draco.LanguageServer/Capabilities/Rename.cs index 33d492796..c756325cf 100644 --- a/src/Draco.LanguageServer/Capabilities/Rename.cs +++ b/src/Draco.LanguageServer/Capabilities/Rename.cs @@ -85,7 +85,7 @@ private static IEnumerable FindAllAppearances( private static Lsp.Model.TextEdit RenameNode(SyntaxNode original, string name) => original switch { - ParameterSyntax p => RenameToken(p.Name, name), + NormalParameterSyntax p => RenameToken(p.Name, name), GenericParameterSyntax g => RenameToken(g.Name, name), FunctionDeclarationSyntax f => RenameToken(f.Name, name), VariableDeclarationSyntax v => RenameToken(v.Name, name), From cb8465a9b4a49b6f22745c9ba70a57dba1c13349 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 28 Oct 2024 01:32:09 +0100 Subject: [PATCH 044/109] more pr feedback --- src/Draco.Compiler/Internal/Binding/ClassBinder.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs index 525d66959..b9bf7a5de 100644 --- a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -19,7 +19,6 @@ internal sealed class ClassBinder(Binder parent, TypeSymbol symbol) : Binder(par internal override void LookupLocal(LookupResult result, string name, ref LookupFlags flags, Predicate allowSymbol, SyntaxNode? currentReference) { - // copied from the function binder, as far as i understand it, it should be the same. foreach (var typeParam in this.symbol.GenericParameters) { if (typeParam.Name != name) continue; @@ -28,8 +27,6 @@ internal override void LookupLocal(LookupResult result, string name, ref LookupF break; } - if (flags.HasFlag(LookupFlags.DisallowLocals)) return; - foreach (var member in this.symbol.Members) { if (member.Name != name) continue; From c24b8196899fac1b2418c2248d8b4459f948c141 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Mon, 28 Oct 2024 19:38:33 +0100 Subject: [PATCH 045/109] wip --- src/Draco.Compiler/Internal/Binding/Binder_Expression.cs | 9 +++++---- src/Draco.Compiler/Internal/Binding/LocalBinder.cs | 4 +--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index 52e414482..e711f85bd 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -715,16 +715,17 @@ private async BindingTask BindIndexExpression(IndexExpressionSy private BindingTask BindThisExpression(ThisExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { - var function = ((SyntaxFunctionSymbol)this.ContainingSymbol!); - var thisArg = function.ThisArgument as ParameterSymbol; + var function = this.ContainingSymbol as SyntaxFunctionSymbol; + var thisArg = function?.ThisArgument as ParameterSymbol; if (thisArg is null) { diagnostics.Add(Diagnostic.Create( template: SymbolResolutionErrors.NoThisInStaticMethod, location: syntax.Location, formatArgs: [this.ContainingSymbol!.Name])); - var type = function.ContainingSymbol as TypeSymbol ?? WellKnownTypes.ErrorType; - thisArg = new ErrorThisParameterSymbol(type, function); + var type = function?.ContainingSymbol as TypeSymbol ?? WellKnownTypes.ErrorType; + + thisArg = new ErrorThisParameterSymbol(type, function as FunctionSymbol ?? new ErrorFunctionSymbol(0)); } var boundThis = new BoundParameterExpression(syntax, thisArg); return BindingTask.FromResult(boundThis); diff --git a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs index ef569501b..61ccbdef0 100644 --- a/src/Draco.Compiler/Internal/Binding/LocalBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/LocalBinder.cs @@ -169,9 +169,7 @@ private void Build() { FunctionDeclarationSyntax function => new SourceFunctionSymbol(this.ContainingSymbol, function), NormalParameterSyntax parameter => new SourceParameterSymbol((FunctionSymbol)this.ContainingSymbol, parameter), - VariableDeclarationSyntax variable => variable.FieldKeyword is null ? - new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable) : - new SourceFieldSymbol((TypeSymbol)this.ContainingSymbol, variable), + VariableDeclarationSyntax variable => new SourceLocalSymbol(this.ContainingSymbol, new TypeVariable(localCount), variable), LabelDeclarationSyntax label => new SourceLabelSymbol(this.ContainingSymbol, label), _ => null, }; From ce72219977a6c1f13c74a952de069446e9b39b04 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 30 Oct 2024 00:26:19 +0100 Subject: [PATCH 046/109] Added error on this resolution. --- .../Internal/Binding/Binder_Expression.cs | 32 ++++++++++++++----- .../Binding/SymbolResolutionErrors.cs | 6 ++++ 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index e711f85bd..bbc0ddbf5 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -14,6 +14,7 @@ using Draco.Compiler.Internal.Symbols.Error; using Draco.Compiler.Internal.Symbols.Syntax; using Draco.Compiler.Internal.Symbols.Synthetized; +using static System.Runtime.InteropServices.JavaScript.JSType; namespace Draco.Compiler.Internal.Binding; @@ -715,20 +716,35 @@ private async BindingTask BindIndexExpression(IndexExpressionSy private BindingTask BindThisExpression(ThisExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { - var function = this.ContainingSymbol as SyntaxFunctionSymbol; - var thisArg = function?.ThisArgument as ParameterSymbol; - if (thisArg is null) + if (this.ContainingSymbol is not SyntaxFunctionSymbol function || this.ContainingSymbol == null) { diagnostics.Add(Diagnostic.Create( + template: SymbolResolutionErrors.IllegalThis, + location: syntax.Location + )); + return BindingTask.FromResult( + new BoundParameterExpression( + syntax, + new ErrorThisParameterSymbol(WellKnownTypes.ErrorType, new ErrorFunctionSymbol(0)))); + } + + var thisArg = function.ThisArgument; + if (thisArg is not null) + { + var boundThis = new BoundParameterExpression(syntax, thisArg); + return BindingTask.FromResult(boundThis); + } + + diagnostics.Add(Diagnostic.Create( template: SymbolResolutionErrors.NoThisInStaticMethod, location: syntax.Location, formatArgs: [this.ContainingSymbol!.Name])); - var type = function?.ContainingSymbol as TypeSymbol ?? WellKnownTypes.ErrorType; + var type = function.ContainingSymbol as TypeSymbol ?? WellKnownTypes.ErrorType; - thisArg = new ErrorThisParameterSymbol(type, function as FunctionSymbol ?? new ErrorFunctionSymbol(0)); - } - var boundThis = new BoundParameterExpression(syntax, thisArg); - return BindingTask.FromResult(boundThis); + return BindingTask.FromResult( + new BoundParameterExpression( + syntax, + new ErrorThisParameterSymbol(type, function))); } private async BindingTask BindGenericExpression(GenericExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) diff --git a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs index 4e3748962..fb75f1b21 100644 --- a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs +++ b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs @@ -211,4 +211,10 @@ internal static class SymbolResolutionErrors severity: DiagnosticSeverity.Error, format: "illegal return expression outside of function definition", code: Code(23)); + + public static readonly DiagnosticTemplate IllegalThis = DiagnosticTemplate.Create( + title: "ilegal this", + severity: DiagnosticSeverity.Error, + format: "illegal this expression outside of a function definition", + code: Code(24)); } From 4de8931cbef28f28038a98b8158f24586b0255d1 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 30 Oct 2024 00:27:21 +0100 Subject: [PATCH 047/109] Update src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs Co-authored-by: LPeter1997 --- src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs index 7a49c61fa..c348fcae4 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs @@ -5,7 +5,8 @@ using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.OptimizingIr.Model; -internal class Class(Module declaringModule, TypeSymbol symbol) : IClass + +internal sealed class Class(Module declaringModule, TypeSymbol symbol) : IClass { public TypeSymbol Symbol { get; } = symbol; From a18510df76e897af6983fb72f43690ec7a771ed7 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 30 Oct 2024 00:29:00 +0100 Subject: [PATCH 048/109] Update src/Draco.Compiler/Internal/Syntax/Syntax.xml Co-authored-by: LPeter1997 --- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index bf5a7dade..faddfb390 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -1375,7 +1375,7 @@ - The keyword this, representing the type instance. + The expression referencing the receiver of a member function. From 5db53095d5fa65fc8c055be85709c2ac9a912b7a Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 30 Oct 2024 00:29:13 +0100 Subject: [PATCH 049/109] Update src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs Co-authored-by: LPeter1997 --- src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index 04b048b42..d9a0ca311 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -55,7 +55,6 @@ public int GetParameterIndex(ParameterSymbol symbol) var idx = this.Symbol.Parameters.IndexOf(symbol); if (idx == -1) throw new System.ArgumentOutOfRangeException(nameof(symbol)); return isStaticMethod ? idx : idx + 1; - } public BasicBlock DefineBasicBlock(LabelSymbol symbol) From 2bdf4acc1ca6b6eab28e72b139ab661a405e2235 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Wed, 30 Oct 2024 09:32:55 +0100 Subject: [PATCH 050/109] Added tests for illegal this. --- .../Semantics/SymbolResolutionTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs index 9711e1959..0e811fc75 100644 --- a/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/SymbolResolutionTests.cs @@ -4079,4 +4079,26 @@ public void ReturningInGlobalBlockIsIllegal() Assert.Single(diags); AssertDiagnostics(diags, SymbolResolutionErrors.IllegalReturn); } + + [Fact] + public void ThisExpressionInGlobalContextIsIllegal() + { + // val a = this; + + var main = SyntaxTree.Create(CompilationUnit( + ImmutableVariableDeclaration( + true, + "a", + value: ThisExpression()))); + + // Act + + var compilation = CreateCompilation(main); + var semanticModel = compilation.GetSemanticModel(main); + var diags = semanticModel.Diagnostics; + + // Assert + Assert.Single(diags); + AssertDiagnostics(diags, SymbolResolutionErrors.IllegalThis); + } } From 4b83f012e0b4a680516c8a9ec2dc554b93e84a08 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 17:00:34 +0100 Subject: [PATCH 051/109] Update Syntax.xml --- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 50350c114..7040dcb57 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -21,11 +21,13 @@ + + @@ -36,15 +38,12 @@ - - - - - + + @@ -692,7 +691,7 @@ The optional global keyword that mark this variable as a global. - + From e20a311769e95123b727b5f1137a7ef1d7d1b98a Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 17:24:55 +0100 Subject: [PATCH 052/109] Builds --- .../Semantics/AttributeTests.cs | 4 +- .../Semantics/ControlFlowGraphTests.cs | 18 ++-- .../Semantics/OverloadingTests.cs | 12 +-- .../Semantics/ReturnsOnAllPathsTests.cs | 8 +- .../Api/Syntax/SyntaxFactory.cs | 84 ++++++++++++++++--- .../Symbols/Source/SourceClassSymbol.cs | 2 +- .../Symbols/Source/SourceModuleSymbol.cs | 6 +- src/Draco.Compiler/Internal/Syntax/Parser.cs | 39 +++++---- 8 files changed, 119 insertions(+), 54 deletions(-) diff --git a/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs b/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs index aee64a4fd..b2c8cfbd5 100644 --- a/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/AttributeTests.cs @@ -103,7 +103,7 @@ public void AttributeIsWrittenIntoMetadata() FunctionDeclaration( [Attribute(NameType("ObsoleteAttribute"), StringExpression("do not use this function"))], "foo", - ParameterList(NormalParameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), + ParameterList(Parameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), null, BlockFunctionBody()))); @@ -132,7 +132,7 @@ public void AttributeReferencesTheSymbol() FunctionDeclaration( [Attribute(NameType("ObsoleteAttribute"), StringExpression("do not use this function"))], "foo", - ParameterList(NormalParameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), + ParameterList(Parameter([Attribute(NameType("AllowNullAttribute"))], "arg", NameType("object"))), null, BlockFunctionBody()))); diff --git a/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs b/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs index 2d2c20a6c..22016e326 100644 --- a/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/ControlFlowGraphTests.cs @@ -83,7 +83,7 @@ public async Task IfElse() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(IfExpression( @@ -149,7 +149,7 @@ public async Task EarlyReturn() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( ExpressionStatement(CallExpression(NameExpression("bar"))), @@ -181,7 +181,7 @@ public async Task ConditionalGotoInAssignment() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), null, BlockFunctionBody( DeclarationStatement(VarDeclaration("x", null, IfExpression( @@ -211,14 +211,14 @@ public async Task ForLoop() var program = SyntaxTree.Create(CompilationUnit( FunctionDeclaration( "main", - ParameterList(NormalParameter("s", GenericType(NameType("Array"), NameType("int32")))), + ParameterList(Parameter("s", GenericType(NameType("Array"), NameType("int32")))), null, BlockFunctionBody( ExpressionStatement(ForExpression( "i", NameExpression("s"), CallExpression(NameExpression("bar"), NameExpression("i")))))), - FunctionDeclaration("bar", ParameterList(NormalParameter("x", NameType("int32"))), null, BlockFunctionBody()))); + FunctionDeclaration("bar", ParameterList(Parameter("x", NameType("int32"))), null, BlockFunctionBody()))); // Act var cfg = FunctionToCfg(program); @@ -243,10 +243,10 @@ public async Task ChainedComparison() FunctionDeclaration( "foo", ParameterList( - NormalParameter("a", NameType("int32")), - NormalParameter("b", NameType("int32")), - NormalParameter("c", NameType("int32")), - NormalParameter("d", NameType("int32"))), + Parameter("a", NameType("int32")), + Parameter("b", NameType("int32")), + Parameter("c", NameType("int32")), + Parameter("d", NameType("int32"))), null, InlineFunctionBody(RelationalExpression( BlockExpression([ExpressionStatement(CallExpression(NameExpression("bar")))], NameExpression("a")), diff --git a/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs b/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs index 7987b5067..f8b21befe 100644 --- a/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/OverloadingTests.cs @@ -18,34 +18,34 @@ public sealed class OverloadingTests private static IEnumerable GetGenericListOverloads() => [ FunctionDeclaration( "foo", - ParameterList(NormalParameter("l", GenericType(NameType("List"), NameType("int32")))), + ParameterList(Parameter("l", GenericType(NameType("List"), NameType("int32")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(NormalParameter("l", GenericType(NameType("List"), NameType("string")))), + ParameterList(Parameter("l", GenericType(NameType("List"), NameType("string")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(NormalParameter("l", GenericType(NameType("List"), NameType("T")))), + ParameterList(Parameter("l", GenericType(NameType("List"), NameType("T")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(NormalParameter("l", GenericType(NameType("IEnumerable"), NameType("int32")))), + ParameterList(Parameter("l", GenericType(NameType("IEnumerable"), NameType("int32")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", - ParameterList(NormalParameter("l", GenericType(NameType("IEnumerable"), NameType("string")))), + ParameterList(Parameter("l", GenericType(NameType("IEnumerable"), NameType("string")))), null, BlockFunctionBody()), FunctionDeclaration( "foo", GenericParameterList(GenericParameter("T")), - ParameterList(NormalParameter("l", GenericType(NameType("IEnumerable"), NameType("T")))), + ParameterList(Parameter("l", GenericType(NameType("IEnumerable"), NameType("T")))), null, BlockFunctionBody()), ]; diff --git a/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs b/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs index efc977dcd..0c65af6c7 100644 --- a/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs +++ b/src/Draco.Compiler.Tests/Semantics/ReturnsOnAllPathsTests.cs @@ -98,7 +98,7 @@ public void NonUnitMethodReturnsConditionally() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(IfExpression( @@ -124,7 +124,7 @@ public void NonUnitMethodReturnsConditionallyOnBothBranches() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(IfExpression( @@ -151,7 +151,7 @@ public void NonUnitMethodReturnsConditionallyButThenUnconditionally() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(IfExpression( @@ -177,7 +177,7 @@ public void NonUnitMethodReturnsInConditionalLoop() // } var tree = SyntaxTree.Create(CompilationUnit(FunctionDeclaration( "foo", - ParameterList(NormalParameter("b", NameType("bool"))), + ParameterList(Parameter("b", NameType("bool"))), NameType("int32"), BlockFunctionBody( ExpressionStatement(WhileExpression( diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index 593758a7b..d783fba93 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -101,9 +101,9 @@ public static SeparatedSyntaxList ParameterList(params Paramete public static ParameterSyntax Parameter(string name, TypeSyntax type) => Parameter([], name, type); public static ParameterSyntax Parameter(IEnumerable attributes, string name, TypeSyntax type) => - Parameter(SyntaxList(attributes), null, Identifier(name), Colon, type); + NormalParameter(SyntaxList(attributes), null, Identifier(name), Colon, type); public static ParameterSyntax VariadicParameter(string name, TypeSyntax type) => - Parameter(SyntaxList(), Ellipsis, Identifier(name), Colon, type); + NormalParameter(SyntaxList(), Ellipsis, Identifier(name), Colon, type); public static SeparatedSyntaxList GenericParameterList(IEnumerable parameters) => SeparatedSyntaxList(Comma, parameters); @@ -173,57 +173,114 @@ public static VariableDeclarationSyntax ValDeclaration( string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => - VariableDeclaration([], null, false, false, name, type, value); + VariableDeclaration( + attributes: [], null, + isGlobal: false, + isField: false, + isMutable: false, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax VarDeclaration( string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => - VariableDeclaration([], null, false, true, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration( + attributes: [], + visibility: null, + isGlobal: false, + isField: false, + isMutable: true, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax FieldValDeclaration( string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => - VariableDeclaration([], null, true, false, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration( + attributes: [], + visibility: null, + isGlobal: false, + isField: true, + isMutable: false, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax FieldVarDeclaration( string name, TypeSyntax? type = null, - ExpressionSyntax? value = null) => - VariableDeclaration([], null, true, true, name, type, value); + ExpressionSyntax? value = null) => VariableDeclaration( + attributes: [], + visibility: null, + isGlobal: false, + isField: true, + isMutable: true, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax ValDeclaration( Visibility? visibility, string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => - VariableDeclaration([], visibility, false, false, name, type, value); + VariableDeclaration( + attributes: [], + visibility: visibility, + isGlobal: false, + isField: false, + isMutable: false, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax VarDeclaration( Visibility? visibility, string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => - VariableDeclaration([], visibility, false, true, name, type, value); + VariableDeclaration( + attributes: [], + visibility: visibility, + isGlobal: false, + false, true, name, type, value); public static VariableDeclarationSyntax FieldValDeclaration( Visibility? visibility, string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => - VariableDeclaration([], visibility, true, false, name, type, value); + VariableDeclaration( + attributes: [], + visibility: visibility, + isGlobal: false, + isField: true, + isMutable: false, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax FieldVarDeclaration( Visibility? visibility, string name, TypeSyntax? type = null, ExpressionSyntax? value = null) => - VariableDeclaration([], visibility, true, true, name, type, value); + VariableDeclaration( + attributes: [], + visibility: visibility, + isGlobal: false, + isField: true, + isMutable: true, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax VariableDeclaration( IEnumerable attributes, Visibility? visibility, + bool isGlobal, bool isField, bool isMutable, string name, @@ -231,6 +288,7 @@ public static VariableDeclarationSyntax VariableDeclaration( ExpressionSyntax? value = null) => VariableDeclaration( attributes, Visibility(visibility), + isGlobal ? TokenKind.KeywordGlobal : null, isField ? TokenKind.KeywordField : null, isMutable ? TokenKind.KeywordVar : TokenKind.KeywordVal, name, diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 620153e99..de4062247 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -97,7 +97,7 @@ private Symbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declara case FunctionDeclarationSyntax functionSyntax: return new SourceFunctionSymbol(this, functionSyntax); case VariableDeclarationSyntax fieldSyntax: - if (fieldSyntax.FieldKeyword is null) throw new NotImplementedException(); + if (fieldSyntax.FieldModifier is null) throw new NotImplementedException(); return new SourceFieldSymbol(this, fieldSyntax); default: throw new NotImplementedException(); // TODO implement this diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs index fd028c5f2..c5302f34a 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs @@ -108,11 +108,11 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) private IEnumerable BuildMember(Declaration declaration) => declaration switch { - FunctionDeclaration f => this.BuildFunction(f), - MergedModuleDeclaration m => this.BuildModule(m), + FunctionDeclaration f => [this.BuildFunction(f)], + MergedModuleDeclaration m => [this.BuildModule(m)], GlobalDeclaration g when g.Syntax.FieldModifier is not null => [this.BuildGlobalField(g)], GlobalDeclaration g when g.Syntax.FieldModifier is null => this.BuildGlobalProperty(g), - ClassDeclaration c => this.BuildClass(c), + ClassDeclaration c => [this.BuildClass(c)], _ => throw new ArgumentOutOfRangeException(nameof(declaration)), }; diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 8def6c5dd..64b8861db 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -193,9 +193,11 @@ private ExpressionParserDelegate BinaryRight(params TokenKind[] operators) => le TokenKind.KeywordImport, TokenKind.KeywordField, TokenKind.KeywordFunc, + TokenKind.KeywordGlobal, TokenKind.KeywordModule, TokenKind.KeywordVar, TokenKind.KeywordVal, + TokenKind.KeywordValue, ]; /// @@ -374,31 +376,24 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) { var attributes = this.ParseAttributeList(); var visibility = this.ParseVisibilityModifier(); - var global = this.ParseGlobalModifier(); // todo: check for global on other constructions and show custom error. switch (this.PeekKind()) { case TokenKind.KeywordImport: return this.ParseImportDeclaration(attributes, visibility); case TokenKind.KeywordValue: - { - var valueKeyword = this.Expect(TokenKind.KeywordValue); - return this.ParseClassDeclaration(visibility: visibility, global: global, valueType: valueKeyword); - } case TokenKind.KeywordClass: - return this.ParseClassDeclaration(visibility: visibility, global: global, valueType: null); + return this.ParseClassDeclaration(visibility); case TokenKind.KeywordFunc: return this.ParseFunctionDeclaration(attributes, visibility, context); case TokenKind.KeywordModule: return this.ParseModuleDeclaration(attributes, visibility, context); - case TokenKind.KeywordField: - var fieldToken = this.Advance(); - return this.ParseVariableDeclaration(attributes, visibility, global, fieldToken, context); case TokenKind.KeywordVar: case TokenKind.KeywordVal: case TokenKind.KeywordField: + case TokenKind.KeywordGlobal: return this.ParseVariableDeclaration(attributes, visibility, context); case TokenKind.Identifier when this.PeekKind(1) == TokenKind.Colon: @@ -543,10 +538,11 @@ private ImportPathSyntax ParseImportPath() /// Parses a class declaration. /// /// Optional visibility modifier token. - /// Optional valuetype modifier token. /// The parsed . - private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, SyntaxToken? global, SyntaxToken? valueType) + private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility) { + this.Matches(TokenKind.KeywordGlobal, out var valueModifier); + // Class keyword and name of the class var classKeyword = this.Expect(TokenKind.KeywordClass); var name = this.Expect(TokenKind.Identifier); @@ -559,7 +555,7 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility, Sy return new ClassDeclarationSyntax( visibility, - valueType, + valueModifier, classKeyword, name, generics, @@ -618,7 +614,6 @@ private BlockClassBodySyntax ParseBlockClassBody() private VariableDeclarationSyntax ParseVariableDeclaration( SyntaxList? attributes, SyntaxToken? visibility, - SyntaxToken? global, DeclarationContext context) { if (context == DeclarationContext.Local && attributes is not null) @@ -632,9 +627,12 @@ private VariableDeclarationSyntax ParseVariableDeclaration( this.AddDiagnostic(visibility, info); } + // Global modifier + this.Matches(TokenKind.KeywordGlobal, out var globalModifier); + // TODO: Check where this is correct + // Field modifier - var fieldModifier = null as SyntaxToken; - this.Matches(TokenKind.KeywordField, out fieldModifier); + this.Matches(TokenKind.KeywordField, out var fieldModifier); if (context == DeclarationContext.Local && fieldModifier is not null) { var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedFieldModifier); @@ -660,7 +658,16 @@ private VariableDeclarationSyntax ParseVariableDeclaration( // Eat semicolon at the end of declaration var semicolon = this.Expect(TokenKind.Semicolon); - return new VariableDeclarationSyntax(attributes, visibility, fieldModifier, keyword, identifier, type, assignment, semicolon); + return new VariableDeclarationSyntax( + attributes, + visibility, + globalModifier, + fieldModifier, + keyword, + identifier, + type, + assignment, + semicolon); } From d69644826bca2b0ae7af00c8c569a61db8d8f376 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 17:27:28 +0100 Subject: [PATCH 053/109] Update Parser.cs --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 64b8861db..085301672 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -541,7 +541,7 @@ private ImportPathSyntax ParseImportPath() /// The parsed . private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility) { - this.Matches(TokenKind.KeywordGlobal, out var valueModifier); + this.Matches(TokenKind.KeywordValue, out var valueModifier); // Class keyword and name of the class var classKeyword = this.Expect(TokenKind.KeywordClass); From e3dd5d0ce762387ee4453c24ce27a9807e8a542a Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 17:28:35 +0100 Subject: [PATCH 054/109] Update Parser.cs --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 085301672..2e66fbe80 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -190,6 +190,7 @@ private ExpressionParserDelegate BinaryRight(params TokenKind[] operators) => le /// private static readonly TokenKind[] declarationStarters = [ + TokenKind.KeywordClass, TokenKind.KeywordImport, TokenKind.KeywordField, TokenKind.KeywordFunc, From 81a95ab4ea431db7eb1fcc4fd15a2ee00567d4bc Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 17:29:06 +0100 Subject: [PATCH 055/109] Update Parser.cs --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 2e66fbe80..2eca70903 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -384,6 +384,7 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordValue: case TokenKind.KeywordClass: + // TODO: Attributes? return this.ParseClassDeclaration(visibility); case TokenKind.KeywordFunc: From 261b0761b1fd0bbe089e457d304e2178013cb791 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 17:30:45 +0100 Subject: [PATCH 056/109] Update Lexer.cs --- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 0d9c94714..2ee6f5148 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -328,6 +328,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) var tokenKind = ident.Span switch { "and" => TokenKind.KeywordAnd, + "class" => TokenKind.KeywordClass, "else" => TokenKind.KeywordElse, "false" => TokenKind.KeywordFalse, "field" => TokenKind.KeywordField, From 541f94148c24d7e082c788b9a7b02f3110fdfa88 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 30 Oct 2024 20:20:57 +0100 Subject: [PATCH 057/109] Yeeted unit --- .../OverloadResolution/CallCandidate.cs | 6 +- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 208 ++++++++++++------ src/Draco.Compiler/Internal/Utilities/Unit.cs | 10 - 3 files changed, 145 insertions(+), 79 deletions(-) delete mode 100644 src/Draco.Compiler/Internal/Utilities/Unit.cs diff --git a/src/Draco.Compiler/Internal/Solver/OverloadResolution/CallCandidate.cs b/src/Draco.Compiler/Internal/Solver/OverloadResolution/CallCandidate.cs index c920f719f..6bb0e17e6 100644 --- a/src/Draco.Compiler/Internal/Solver/OverloadResolution/CallCandidate.cs +++ b/src/Draco.Compiler/Internal/Solver/OverloadResolution/CallCandidate.cs @@ -13,8 +13,8 @@ internal static class CallCandidate public static CallCandidate Create(FunctionSymbol function) => CallCandidate.Create(function); - public static CallCandidate Create(FunctionTypeSymbol functionType) => - CallCandidate.Create(functionType); + public static CallCandidate Create(FunctionTypeSymbol functionType) => + CallCandidate.Create(functionType); } /// @@ -27,7 +27,7 @@ public static CallCandidate Create(FunctionSymbol function) => new(function.Parameters, function.IsVariadic, function); // TODO: Can a function type be variadic? This is probably something we should specify... - public static CallCandidate Create(FunctionTypeSymbol functionType) => + public static CallCandidate Create(FunctionTypeSymbol functionType) => new(functionType.Parameters, false, default); /// diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 2ee6f5148..8bd6edd8f 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -160,29 +160,26 @@ public SyntaxToken Lex() /// /// Lexes tokens that can be found in regular code. /// - /// The lexed . - private Unit LexNormal() + private void LexNormal() { - Unit TakeBasic(TokenKind tokenKind, int length) + void TakeBasic(TokenKind tokenKind, int length) { this.Advance(length); this.tokenBuilder.SetKind(tokenKind); - return default; } - Unit TakeWithText(TokenKind tokenKind, int length) + void TakeWithText(TokenKind tokenKind, int length) { this.tokenBuilder .SetKind(tokenKind) .SetText(this.AdvanceWithText(length)); - return default; } // First check for end of source here if (this.SourceReader.IsEnd) { this.tokenBuilder.SetKind(TokenKind.EndOfInput); - return default; + return; } var mode = this.CurrentMode; @@ -191,60 +188,136 @@ Unit TakeWithText(TokenKind tokenKind, int length) // Punctuation switch (ch) { - case '(': return TakeBasic(TokenKind.ParenOpen, 1); - case ')': return TakeBasic(TokenKind.ParenClose, 1); + case '(': + TakeBasic(TokenKind.ParenOpen, 1); + return; + case ')': + TakeBasic(TokenKind.ParenClose, 1); + return; case '{': if (mode.IsInterpolation) this.PushMode(mode.Kind, 0); - return TakeBasic(TokenKind.CurlyOpen, 1); + TakeBasic(TokenKind.CurlyOpen, 1); + return; case '}': if (mode.IsInterpolation) { this.PopMode(); // If we are not in interpolation anymore, this is an interpolation end token - if (!this.CurrentMode.IsInterpolation) return TakeBasic(TokenKind.InterpolationEnd, 1); + if (!this.CurrentMode.IsInterpolation) + { + TakeBasic(TokenKind.InterpolationEnd, 1); + return; + } } - return TakeBasic(TokenKind.CurlyClose, 1); - case '[': return TakeBasic(TokenKind.BracketOpen, 1); - case ']': return TakeBasic(TokenKind.BracketClose, 1); - + TakeBasic(TokenKind.CurlyClose, 1); + return; + case '[': + TakeBasic(TokenKind.BracketOpen, 1); + return; + case ']': + TakeBasic(TokenKind.BracketClose, 1); + return; case '.': - if (this.Peek(1) == '.' && this.Peek(2) == '.') return TakeBasic(TokenKind.Ellipsis, 3); - return TakeBasic(TokenKind.Dot, 1); - case ',': return TakeBasic(TokenKind.Comma, 1); - case ':': return TakeBasic(TokenKind.Colon, 1); - case ';': return TakeBasic(TokenKind.Semicolon, 1); + if (this.Peek(1) == '.' && this.Peek(2) == '.') + { + TakeBasic(TokenKind.Ellipsis, 3); + return; + } + TakeBasic(TokenKind.Dot, 1); + return; + case ',': + TakeBasic(TokenKind.Comma, 1); + return; + case ':': + TakeBasic(TokenKind.Colon, 1); + return; + case ';': + TakeBasic(TokenKind.Semicolon, 1); + return; case '+': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.PlusAssign, 2); - return TakeBasic(TokenKind.Plus, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.PlusAssign, 2); + return; + } + TakeBasic(TokenKind.Plus, 1); + return; case '-': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.MinusAssign, 2); - return TakeBasic(TokenKind.Minus, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.MinusAssign, 2); + return; + } + TakeBasic(TokenKind.Minus, 1); + return; case '*': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.StarAssign, 2); - return TakeBasic(TokenKind.Star, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.StarAssign, 2); + return; + } + TakeBasic(TokenKind.Star, 1); + return; case '/': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.SlashAssign, 2); - return TakeBasic(TokenKind.Slash, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.SlashAssign, 2); + return; + } + TakeBasic(TokenKind.Slash, 1); + return; case '<': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.LessEqual, 2); - return TakeBasic(TokenKind.LessThan, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.LessEqual, 2); + return; + } + TakeBasic(TokenKind.LessThan, 1); + return; case '>': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.GreaterEqual, 2); - return TakeBasic(TokenKind.GreaterThan, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.GreaterEqual, 2); + return; + } + TakeBasic(TokenKind.GreaterThan, 1); + return; case '=': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.Equal, 2); - return TakeBasic(TokenKind.Assign, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.Equal, 2); + return; + } + TakeBasic(TokenKind.Assign, 1); + return; case '!': - if (this.Peek(1) == '=') return TakeBasic(TokenKind.NotEqual, 2); - return TakeBasic(TokenKind.CNot, 1); - case '%': return TakeBasic(TokenKind.CMod, 1); + if (this.Peek(1) == '=') + { + TakeBasic(TokenKind.NotEqual, 2); + return; + } + TakeBasic(TokenKind.CNot, 1); + return; + case '%': + TakeBasic(TokenKind.CMod, 1); + return; case '|': - if (this.Peek(1) == '|') return TakeBasic(TokenKind.COr, 2); + if (this.Peek(1) == '|') + { + TakeBasic(TokenKind.COr, 2); + return; + } break; case '&': - if (this.Peek(1) == '&') return TakeBasic(TokenKind.CAnd, 2); + if (this.Peek(1) == '&') + { + TakeBasic(TokenKind.CAnd, 2); + return; + } break; - case '@': return TakeBasic(TokenKind.AtSign, 1); + case '@': + TakeBasic(TokenKind.AtSign, 1); + return; } // Numeric literals @@ -264,7 +337,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) .SetKind(TokenKind.LiteralInteger) .SetText($"0{radix}{view}") .SetValue(value); - return default; + return; } var offset = 1; var isFloat = false; @@ -292,7 +365,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) this.tokenBuilder .SetKind(TokenKind.LiteralFloat) .SetText(this.Advance(offset).Span.ToString()); - return default; + return; } while (IsDigit(this.Peek(offset))) ++offset; } @@ -306,7 +379,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) .SetKind(TokenKind.LiteralFloat) .SetText(floatView.ToString()) .SetValue(floatValue); - return default; + return; } // Regular integer @@ -315,7 +388,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) .SetKind(TokenKind.LiteralInteger) .SetText(decimalView) .SetValue(decimalValue); - return default; + return; } // Identifier-like tokens @@ -365,7 +438,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) .SetKind(TokenKind.Identifier) .SetText(identStr) .SetValue(identStr); - return default; + return; } else { @@ -373,7 +446,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) this.tokenBuilder.SetKind(tokenKind); if (tokenKind == TokenKind.KeywordTrue) this.tokenBuilder.SetValue(true); if (tokenKind == TokenKind.KeywordFalse) this.tokenBuilder.SetValue(false); - return default; + return; } } @@ -393,7 +466,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) .SetKind(TokenKind.LiteralCharacter) .SetText(errText) .SetValue(new Rune(' ')); - return default; + return; } var resultChar = default(Rune); if (ch2 == '\\') @@ -451,7 +524,7 @@ Unit TakeWithText(TokenKind tokenKind, int length) .SetKind(TokenKind.LiteralCharacter) .SetText(text) .SetValue(resultChar); - return default; + return; } // String literal starts @@ -465,23 +538,26 @@ Unit TakeWithText(TokenKind tokenKind, int length) { // Mutli-line string opening quotes this.PushMode(ModeKind.MultiLineString, extendedDelims); - return TakeWithText(TokenKind.MultiLineStringStart, offset + 3); + TakeWithText(TokenKind.MultiLineStringStart, offset + 3); + return; } // Single-line string opening quote this.PushMode(ModeKind.LineString, extendedDelims); - return TakeWithText(TokenKind.LineStringStart, offset + 1); + TakeWithText(TokenKind.LineStringStart, offset + 1); + return; } } // Unknown - return TakeWithText(TokenKind.Unknown, 1); + TakeWithText(TokenKind.Unknown, 1); + return; } /// /// Lexes a token that can be part of a string. /// /// The lexed string . - private Unit LexString() + private void LexString() { // Get the largest continuous sequence without linebreaks or interpolation var mode = this.CurrentMode; @@ -492,7 +568,7 @@ private Unit LexString() if (this.SourceReader.IsEnd) { this.tokenBuilder.SetKind(TokenKind.EndOfInput); - return default; + return; } // NOTE: We are checking end of input differently here, because SourceReader.IsEnd is based on its @@ -505,7 +581,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } // Check for closing quotes @@ -555,7 +631,7 @@ private Unit LexString() this.tokenBuilder .SetKind(tokenKind) .SetText(this.AdvanceWithText(endLength)); - return default; + return; } else { @@ -565,7 +641,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } } @@ -589,7 +665,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } // Interpolation @@ -605,7 +681,7 @@ private Unit LexString() this.tokenBuilder .SetKind(TokenKind.InterpolationStart) .SetText(this.AdvanceWithText(mode.ExtendedDelims + 2)); - return default; + return; } else { @@ -615,7 +691,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } } @@ -636,7 +712,7 @@ private Unit LexString() .SetKind(TokenKind.StringNewline) .SetText(this.AdvanceWithText(mode.ExtendedDelims + 1 + whiteCharOffset + length)) .SetValue(string.Empty); - return default; + return; } else { @@ -645,7 +721,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } } } @@ -658,7 +734,7 @@ private Unit LexString() .SetKind(TokenKind.EscapeSequence) .SetText(this.AdvanceWithText(offset)) .SetValue(escaped); - return default; + return; } not_escape_sequence: @@ -678,7 +754,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } else { @@ -707,7 +783,7 @@ private Unit LexString() .SetKind(TokenKind.MultiLineStringEnd) .SetText(this.AdvanceWithText(3 + mode.ExtendedDelims)); this.ParseTrailingTriviaList(); - return default; + return; } not_string_end2: // Just a regular newline, more content to follow @@ -716,7 +792,7 @@ private Unit LexString() .SetKind(TokenKind.StringNewline) .SetText(stringNewlineText) .SetValue(stringNewlineText); - return default; + return; } else { @@ -725,7 +801,7 @@ private Unit LexString() .SetKind(TokenKind.StringContent) .SetText(this.AdvanceWithText(offset)) .SetValue(this.valueBuilder.ToString()); - return default; + return; } } } diff --git a/src/Draco.Compiler/Internal/Utilities/Unit.cs b/src/Draco.Compiler/Internal/Utilities/Unit.cs deleted file mode 100644 index e2e8e94b0..000000000 --- a/src/Draco.Compiler/Internal/Utilities/Unit.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Draco.Compiler.Internal.Utilities; - -/// -/// Utility type for returning nothing as an expression. -/// Usable instead of 'void'. -/// -[ExcludeFromCodeCoverage] -internal readonly record struct Unit; From d6f7b4e781004603ca2c35053dc42704547179d1 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 19:29:12 +0100 Subject: [PATCH 058/109] Update ConstructorFunctionSymbol.cs --- .../Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs index fd3633ded..d3e28aff1 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs @@ -20,8 +20,6 @@ internal sealed class ConstructorFunctionSymbol(FunctionSymbol ctorDefinition) : public override SymbolDocumentation Documentation => ctorDefinition.Documentation; internal override string RawDocumentation => ctorDefinition.RawDocumentation; - public override Symbol? ContainingSymbol { get; } = ctorDefinition; - public override ImmutableArray GenericParameters => InterlockedUtils.InitializeDefault(ref this.genericParameters, this.BuildGenericParameters); private ImmutableArray genericParameters; From dafd12ca46ff1cafa309b82e017d725e8c943fc3 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 20:47:52 +0100 Subject: [PATCH 059/109] Update SyntaxErrors.cs --- src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs b/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs index 291ed36a1..3b629ee02 100644 --- a/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs +++ b/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs @@ -174,15 +174,6 @@ internal static class SyntaxErrors format: "{0} is not a valid {1} in Draco, use {2} instead", code: Code(18)); - /// - /// There is a field declaration in a function. - /// - public static readonly DiagnosticTemplate UnexpectedFieldDeclarationInFunction = DiagnosticTemplate.Create( - title: "unexpected field declaration", - severity: DiagnosticSeverity.Error, - format: "unexpected field declaration", - code: Code(19)); - /// /// Empty generic lists are not allowed. /// @@ -190,7 +181,7 @@ internal static class SyntaxErrors title: "empty generic list", severity: DiagnosticSeverity.Error, format: "empty generic {0} lists are not allowed", - code: Code(20)); + code: Code(19)); /// /// There is a field modifier in a local context. @@ -199,5 +190,5 @@ internal static class SyntaxErrors title: "unexpected field modifier", severity: DiagnosticSeverity.Error, format: "unexpected field modifier in a local context", - code: Code(21)); + code: Code(20)); } From 883abbe68f682abfa67c1712e68af71e21a1924c Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 21:00:34 +0100 Subject: [PATCH 060/109] Update Lexer.cs --- src/Draco.Compiler/Internal/Syntax/Lexer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Syntax/Lexer.cs b/src/Draco.Compiler/Internal/Syntax/Lexer.cs index 8bd6edd8f..4dd2cb388 100644 --- a/src/Draco.Compiler/Internal/Syntax/Lexer.cs +++ b/src/Draco.Compiler/Internal/Syntax/Lexer.cs @@ -407,6 +407,7 @@ void TakeWithText(TokenKind tokenKind, int length) "field" => TokenKind.KeywordField, "for" => TokenKind.KeywordFor, "func" => TokenKind.KeywordFunc, + "global" => TokenKind.KeywordGlobal, "goto" => TokenKind.KeywordGoto, "if" => TokenKind.KeywordIf, "import" => TokenKind.KeywordImport, From 1990d06687d085c4e2d9b7985d4d335b671ec266 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 22:46:29 +0100 Subject: [PATCH 061/109] Cleaned up syntax naming --- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 14 +++++++------- src/Draco.SourceGeneration/TemplateUtils.cs | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 7040dcb57..a6c38aed6 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -516,9 +516,9 @@ The this parameter at the first place in a parameter list. - + - The this keyword, representing the type instance. + The 'this' keyword. @@ -687,9 +687,9 @@ - + - The optional global keyword that mark this variable as a global. + The optional global modifier that marks this variable as a global (static). @@ -1384,13 +1384,13 @@ The expression referencing the receiver of a member function. - + - The this keyword. + The 'this' keyword. + - diff --git a/src/Draco.SourceGeneration/TemplateUtils.cs b/src/Draco.SourceGeneration/TemplateUtils.cs index 1cd10a21d..ce798a54a 100644 --- a/src/Draco.SourceGeneration/TemplateUtils.cs +++ b/src/Draco.SourceGeneration/TemplateUtils.cs @@ -28,7 +28,8 @@ internal static class TemplateUtils "operator", "object", "bool", - "string" + "string", + "this", ]; /// From ae6d486c0664eadfa42c33ca6b8e6fc32875aadc Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 22:59:45 +0100 Subject: [PATCH 062/109] Syntax fixup --- src/Draco.Compiler/Internal/Syntax/Parser.cs | 75 +++++++++---------- src/Draco.Compiler/Internal/Syntax/Syntax.xml | 12 +++ 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 2eca70903..6ee81b492 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -238,7 +238,7 @@ private ExpressionParserDelegate BinaryRight(params TokenKind[] operators) => le TokenKind.Plus, TokenKind.Minus, TokenKind.Star, - TokenKind.KeywordThis + TokenKind.KeywordThis, ]; /// @@ -384,8 +384,7 @@ private DeclarationSyntax ParseDeclaration(DeclarationContext context) case TokenKind.KeywordValue: case TokenKind.KeywordClass: - // TODO: Attributes? - return this.ParseClassDeclaration(visibility); + return this.ParseClassDeclaration(attributes, visibility); case TokenKind.KeywordFunc: return this.ParseFunctionDeclaration(attributes, visibility, context); @@ -539,9 +538,10 @@ private ImportPathSyntax ParseImportPath() /// /// Parses a class declaration. /// + /// Optional attributes on the class. /// Optional visibility modifier token. /// The parsed . - private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility) + private ClassDeclarationSyntax ParseClassDeclaration(SyntaxList? attributes, SyntaxToken? visibility) { this.Matches(TokenKind.KeywordValue, out var valueModifier); @@ -568,42 +568,40 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxToken? visibility) /// Parses the body of a class. /// /// The parsed . - private ClassBodySyntax ParseClassBody() => this.PeekKind() switch + private ClassBodySyntax ParseClassBody() { - TokenKind.Semicolon => this.ParseEmptyClassBody(), - TokenKind.CurlyOpen => this.ParseBlockClassBody(), - _ => throw new NotImplementedException() - }; - - /// - /// Parses an empty class body, which is just a semicolon. - /// - /// The parsed . - private EmptyClassBodySyntax ParseEmptyClassBody() - { - var semicolon = this.Expect(TokenKind.Semicolon); - return new EmptyClassBodySyntax(semicolon); - } - - /// - /// Parses a block class body declared with curly braces. - /// - /// The parsed . - private BlockClassBodySyntax ParseBlockClassBody() - { - var openBrace = this.Expect(TokenKind.CurlyOpen); - var decls = SyntaxList.CreateBuilder(); - while (true) + if (this.Matches(TokenKind.Semicolon, out var semicolon)) + { + return new EmptyClassBodySyntax(semicolon); + } + else if (this.Matches(TokenKind.CurlyOpen, out var openBrace)) { - // Break on the end of the block - if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; + var decls = SyntaxList.CreateBuilder(); + while (true) + { + // Break on the end of the block + if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; - // Parse a declaration - var decl = this.ParseDeclaration(DeclarationContext.Global); - decls.Add(decl); + // Parse a declaration + var decl = this.ParseDeclaration(DeclarationContext.Global); + decls.Add(decl); + } + var closeBrace = this.Expect(TokenKind.CurlyClose); + return new BlockClassBodySyntax(openBrace, decls.ToSyntaxList(), closeBrace); + } + else + { + var input = this.Synchronize(t => t.Kind switch + { + TokenKind.Semicolon or TokenKind.CurlyClose => false, + _ when this.IsDeclarationStarter(DeclarationContext.Global) => false, + _ => true, + }); + var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "class body"); + var node = new UnexpectedClassBodySyntax(input); + this.AddDiagnostic(node, info); + return node; } - var closeBrace = this.Expect(TokenKind.CurlyClose); - return new(openBrace, decls.ToSyntaxList(), closeBrace); } /// @@ -631,7 +629,7 @@ private VariableDeclarationSyntax ParseVariableDeclaration( // Global modifier this.Matches(TokenKind.KeywordGlobal, out var globalModifier); - // TODO: Check where this is correct + // TODO: We need more info to check, if this is an error // Field modifier this.Matches(TokenKind.KeywordField, out var fieldModifier); @@ -672,7 +670,6 @@ private VariableDeclarationSyntax ParseVariableDeclaration( semicolon); } - /// /// Parses a function declaration. /// @@ -1665,8 +1662,6 @@ private SeparatedSyntaxList ParseSeparatedSyntaxList( private SyntaxToken? ParseVisibilityModifier() => IsVisibilityModifier(this.PeekKind()) ? this.Advance() : null; - private SyntaxToken? ParseGlobalModifier() => this.PeekKind() == TokenKind.KeywordGlobal ? this.Advance() : null; - private bool CanBailOut(SyntaxNode node) { if (parserMode != ParserMode.Repl) return false; diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index a6c38aed6..014e44059 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -435,6 +435,18 @@ + + + Unexpected input in class body context. + + + + + The unexpected syntax nodes. + + + + A function declaration. From 1d0e05f9076dbadb2cbe02c03fbb3094a2fcb057 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 31 Oct 2024 23:13:45 +0100 Subject: [PATCH 063/109] Parser done --- .../Services/CodeCompletionTests.cs | 8 +++--- src/Draco.Compiler/Internal/Syntax/Parser.cs | 25 +++++++++++++------ src/Draco.Compiler/Internal/Syntax/Syntax.xml | 6 +++++ .../Internal/Syntax/SyntaxErrors.cs | 9 +++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/Draco.Compiler.Tests/Services/CodeCompletionTests.cs b/src/Draco.Compiler.Tests/Services/CodeCompletionTests.cs index 3be9967ea..bbe202ddb 100644 --- a/src/Draco.Compiler.Tests/Services/CodeCompletionTests.cs +++ b/src/Draco.Compiler.Tests/Services/CodeCompletionTests.cs @@ -38,13 +38,13 @@ public void TestLocalCompletionGlobalVariable() { // TODO: Can we get rid of all this filtering by filtering in the completion service? var completions = GetCompletionWords(""" - val global = 5; + val globalVar = 5; func main(){ var local = gl| } """); - AssertCompletions(completions, "global"); + AssertCompletions(completions, "globalVar"); } [Fact] @@ -78,11 +78,11 @@ func main(){ public void TestGlobalCompletionGlobalVariable() { var completions = GetCompletionWords(""" - val global = 5; + val globalVar = 5; val x = gl| """); - AssertCompletions(completions, "global"); + AssertCompletions(completions, "globalVar"); } [Fact] diff --git a/src/Draco.Compiler/Internal/Syntax/Parser.cs b/src/Draco.Compiler/Internal/Syntax/Parser.cs index 6ee81b492..f2cf3189d 100644 --- a/src/Draco.Compiler/Internal/Syntax/Parser.cs +++ b/src/Draco.Compiler/Internal/Syntax/Parser.cs @@ -38,10 +38,15 @@ internal sealed class Parser( private enum DeclarationContext { /// - /// Global, like in a compilation unit, module, class, ... + /// Global, like in a compilation unit or module. /// Global, + /// + /// Inside a class declaration body. + /// + Class, + /// /// Local to a function body/expression/code-block. /// @@ -556,6 +561,7 @@ private ClassDeclarationSyntax ParseClassDeclaration(SyntaxList var body = this.ParseClassBody(); return new ClassDeclarationSyntax( + attributes, visibility, valueModifier, classKeyword, @@ -583,7 +589,7 @@ private ClassBodySyntax ParseClassBody() if (this.PeekKind() is TokenKind.EndOfInput or TokenKind.CurlyClose) break; // Parse a declaration - var decl = this.ParseDeclaration(DeclarationContext.Global); + var decl = this.ParseDeclaration(DeclarationContext.Class); decls.Add(decl); } var closeBrace = this.Expect(TokenKind.CurlyClose); @@ -594,7 +600,7 @@ private ClassBodySyntax ParseClassBody() var input = this.Synchronize(t => t.Kind switch { TokenKind.Semicolon or TokenKind.CurlyClose => false, - _ when this.IsDeclarationStarter(DeclarationContext.Global) => false, + _ when this.IsDeclarationStarter(DeclarationContext.Class) => false, _ => true, }); var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "class body"); @@ -629,7 +635,11 @@ private VariableDeclarationSyntax ParseVariableDeclaration( // Global modifier this.Matches(TokenKind.KeywordGlobal, out var globalModifier); - // TODO: We need more info to check, if this is an error + if (context != DeclarationContext.Class && globalModifier is not null) + { + var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedGlobalModifier); + this.AddDiagnostic(globalModifier, info); + } // Field modifier this.Matches(TokenKind.KeywordField, out var fieldModifier); @@ -708,7 +718,7 @@ private FunctionDeclarationSyntax ParseFunctionDeclaration( TypeSpecifierSyntax? returnType = null; if (this.PeekKind() == TokenKind.Colon) returnType = this.ParseTypeSpecifier(); - var body = this.ParseFunctionBody(); + var body = this.ParseFunctionBody(context); return new FunctionDeclarationSyntax( attributes, @@ -882,8 +892,9 @@ private GenericParameterSyntax ParseGenericParameter() /// /// Parses a function body. /// + /// The current context we are in. /// The parsed . - private FunctionBodySyntax ParseFunctionBody() + private FunctionBodySyntax ParseFunctionBody(DeclarationContext ctx) { if (this.Matches(TokenKind.Assign, out var assign)) { @@ -906,7 +917,7 @@ private FunctionBodySyntax ParseFunctionBody() var input = this.Synchronize(t => t.Kind switch { TokenKind.Semicolon or TokenKind.CurlyClose => false, - _ when this.IsDeclarationStarter(DeclarationContext.Global) => false, + _ when this.IsDeclarationStarter(ctx) => false, _ => true, }); var info = DiagnosticInfo.Create(SyntaxErrors.UnexpectedInput, formatArgs: "function body"); diff --git a/src/Draco.Compiler/Internal/Syntax/Syntax.xml b/src/Draco.Compiler/Internal/Syntax/Syntax.xml index 014e44059..b153f6662 100644 --- a/src/Draco.Compiler/Internal/Syntax/Syntax.xml +++ b/src/Draco.Compiler/Internal/Syntax/Syntax.xml @@ -341,6 +341,12 @@ A class declaration. + + + The attributes of this class. + + + The visibility modifier keyword possibly starting the declaration. diff --git a/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs b/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs index 3b629ee02..ce9d604f2 100644 --- a/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs +++ b/src/Draco.Compiler/Internal/Syntax/SyntaxErrors.cs @@ -191,4 +191,13 @@ internal static class SyntaxErrors severity: DiagnosticSeverity.Error, format: "unexpected field modifier in a local context", code: Code(20)); + + /// + /// There is a global modifier in a global or local context. + /// + public static readonly DiagnosticTemplate UnexpectedGlobalModifier = DiagnosticTemplate.Create( + title: "unexpected global modifier", + severity: DiagnosticSeverity.Error, + format: "unexpected global modifier outside of class declaration", + code: Code(21)); } From e987b772f48b1c350dd4d63c90f90089c393c039 Mon Sep 17 00:00:00 2001 From: Kuinox Date: Fri, 1 Nov 2024 19:19:58 +0100 Subject: [PATCH 064/109] Some PR feedback. --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 2 +- src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs | 3 +++ src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs | 4 ++-- src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs | 2 +- .../Internal/OptimizingIr/Model/Procedure.cs | 5 ++--- .../Internal/Symbols/Error/ErrorThisParameterSymbol.cs | 7 ++++++- src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs | 2 +- src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs | 2 ++ .../Internal/Symbols/Source/SourceThisParameterSymbol.cs | 1 + 9 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index e7a61045e..06c064c03 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -522,7 +522,7 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parent, ref int ++procIndex; // We encode every class - foreach (var @class in module.Types.Values) + foreach (var @class in module.Classes.Values) { this.EncodeClass(@class, parent: createdModule, fieldIndex: ref fieldIndex, procIndex: ref procIndex); } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index f2849551d..018425cde 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -3,6 +3,9 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; +/// +/// Read-only interface if a +/// internal interface IClass { /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs index 73539fd4b..8831d2d7e 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs @@ -49,9 +49,9 @@ internal interface IModule public IReadOnlyDictionary Procedures { get; } /// - /// The compiled types within this module. + /// The compiled classes within this module. /// - public IReadOnlyDictionary Types { get; } + public IReadOnlyDictionary Classes { get; } /// /// The procedure performing global initialization. diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index 747ef3bce..a314f43ea 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -19,7 +19,7 @@ internal sealed class Module : IModule IReadOnlyDictionary IModule.Submodules => this.submodules; public IDictionary Types => this.types; - IReadOnlyDictionary IModule.Types => this.types; + IReadOnlyDictionary IModule.Classes => this.types; public IReadOnlySet Fields => this.fields; public IReadOnlySet Properties => this.properties; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index d9a0ca311..da4e14c54 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -50,11 +50,10 @@ public Procedure(Module declaringModule, Class? declaringType, FunctionSymbol sy public int GetParameterIndex(ParameterSymbol symbol) { - if (symbol is SourceThisParameterSymbol) return 0; - var isStaticMethod = symbol.ContainingSymbol.IsStatic; + if (symbol.IsThis) return 0; var idx = this.Symbol.Parameters.IndexOf(symbol); if (idx == -1) throw new System.ArgumentOutOfRangeException(nameof(symbol)); - return isStaticMethod ? idx : idx + 1; + return symbol.ContainingSymbol.IsStatic ? idx : idx + 1; } public BasicBlock DefineBasicBlock(LabelSymbol symbol) diff --git a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs index f38453e3f..caa5aa23b 100644 --- a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs @@ -1,6 +1,11 @@ namespace Draco.Compiler.Internal.Symbols.Error; -internal class ErrorThisParameterSymbol(TypeSymbol type, FunctionSymbol containingSymbol) : ParameterSymbol +/// +/// An error this parameter symbol. +/// +/// +/// +internal sealed class ErrorThisParameterSymbol(TypeSymbol type, FunctionSymbol containingSymbol) : ParameterSymbol { public override TypeSymbol Type { get; } = type; public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index af71c2e64..77ebd1a0c 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -78,7 +78,7 @@ public delegate IOperand CodegenDelegate( /// /// The receiver of this function, if it has one. /// - public TypeSymbol? Receiver => this.IsStatic + public TypeSymbol? ReceiverType => this.IsStatic ? null : this.ContainingSymbol as TypeSymbol; diff --git a/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs index 95f4846ab..d2968d14b 100644 --- a/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs @@ -18,6 +18,8 @@ internal abstract partial class ParameterSymbol : LocalSymbol public virtual bool IsVariadic => false; public override bool IsMutable => false; + + public virtual bool IsThis => false; // NOTE: Override for covariant return type public override ParameterSymbol? GenericDefinition => null; public override SymbolKind Kind => SymbolKind.Parameter; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs index 5c11995ef..b2494a41f 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs @@ -9,6 +9,7 @@ internal sealed class SourceThisParameterSymbol(FunctionSymbol containingSymbol, public override string Name => "this"; public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; public override bool IsVariadic => false; + public override bool IsThis => true; public override ThisParameterSyntax DeclaringSyntax { get; } = syntax; public override ImmutableArray Attributes => []; From fbbffa936e788d9c532236a6d180ff2eab202069 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sat, 2 Nov 2024 13:56:15 +0100 Subject: [PATCH 065/109] Update DefaultConstructorSymbol.cs --- .../Symbols/Synthetized/DefaultConstructorSymbol.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs index f1446763e..ebedf1e49 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/DefaultConstructorSymbol.cs @@ -2,12 +2,13 @@ using Draco.Compiler.Internal.BoundTree; using static Draco.Compiler.Internal.BoundTree.BoundTreeFactory; - namespace Draco.Compiler.Internal.Symbols.Synthetized; +/// +/// The default constructor for types without a user-defined constructor. +/// internal sealed class DefaultConstructorSymbol(TypeSymbol containingSymbol) : FunctionSymbol { - public override ImmutableArray Parameters => []; public override TypeSymbol ReturnType { get; } = WellKnownTypes.Unit; @@ -17,8 +18,8 @@ internal sealed class DefaultConstructorSymbol(TypeSymbol containingSymbol) : Fu public override string Name => ".ctor"; - public override Symbol? ContainingSymbol { get; } = containingSymbol; + public override TypeSymbol ContainingSymbol { get; } = containingSymbol; public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; - public override BoundStatement? Body { get; } = ExpressionStatement(null, ReturnExpression(null, BoundUnitExpression.Default)); + public override BoundStatement Body { get; } = ExpressionStatement(ReturnExpression(BoundUnitExpression.Default)); } From 0cd287e1588abf0d0c9ee59753a3dde4054d0277 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sat, 2 Nov 2024 14:07:28 +0100 Subject: [PATCH 066/109] Update SourceThisParameterSymbol.cs --- .../Source/SourceThisParameterSymbol.cs | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs index b2494a41f..24797b47b 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs @@ -1,19 +1,36 @@ +using System; using System.Collections.Immutable; +using System.Linq; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; namespace Draco.Compiler.Internal.Symbols.Source; -internal sealed class SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterSyntax syntax) : ParameterSymbol, ISourceSymbol +/// +/// The 'this' parameter of a function defined in-source. +/// +internal sealed class SourceThisParameterSymbol : ParameterSymbol, ISourceSymbol { public override string Name => "this"; - public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; + public override FunctionSymbol ContainingSymbol { get; } public override bool IsVariadic => false; public override bool IsThis => true; - public override ThisParameterSyntax DeclaringSyntax { get; } = syntax; + public override ThisParameterSyntax DeclaringSyntax { get; } public override ImmutableArray Attributes => []; - public override TypeSymbol Type { get; } = (containingSymbol.ContainingSymbol as TypeSymbol)!; + public override TypeSymbol Type { get; } + + public SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterSyntax syntax) + { + var containingType = containingSymbol.ContainingSymbol?.AncestorChain + .OfType() + .FirstOrDefault() + ?? throw new ArgumentException("the containing symbol of a source this parameter must be a function within a type"); + + this.ContainingSymbol = containingSymbol; + this.DeclaringSyntax = syntax; + this.Type = containingType; + } public void Bind(IBinderProvider binderProvider) { } } From 35e0a51666a8a1682260740a559bf13e34c4b80d Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sat, 2 Nov 2024 18:28:22 +0100 Subject: [PATCH 067/109] Simplification --- .../Symbols/Source/SourceModuleSymbol.cs | 41 +++++-------------- src/Draco.Compiler/Internal/Symbols/Symbol.cs | 22 +++++++--- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs index c5302f34a..664fce64c 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs @@ -6,6 +6,7 @@ using System.Threading; using Draco.Compiler.Api; using Draco.Compiler.Api.Diagnostics; +using Draco.Compiler.Api.Semantics; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; using Draco.Compiler.Internal.Declarations; @@ -72,16 +73,11 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) var result = ImmutableArray.CreateBuilder(); // A declaration can yield multiple members, like an auto-property a getter and setter - foreach (var member in this.declaration.Children.SelectMany(this.BuildMember)) + foreach (var member in this.declaration.Children.Select(this.BuildMember)) { var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); result.Add(member); - - if (member is TypeSymbol typeSymbol) - { - result.AddRange(GetAdditionalSymbols(typeSymbol)); - } - + result.AddRange(GetAdditionalSymbols(member)); // We check for illegal shadowing if (earlierMember is null) continue; @@ -106,32 +102,15 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) return result.ToImmutable(); } - private IEnumerable BuildMember(Declaration declaration) => declaration switch + private Symbol BuildMember(Declaration declaration) => declaration switch { - FunctionDeclaration f => [this.BuildFunction(f)], - MergedModuleDeclaration m => [this.BuildModule(m)], - GlobalDeclaration g when g.Syntax.FieldModifier is not null => [this.BuildGlobalField(g)], - GlobalDeclaration g when g.Syntax.FieldModifier is null => this.BuildGlobalProperty(g), - ClassDeclaration c => [this.BuildClass(c)], + FunctionDeclaration f => new SourceFunctionSymbol(this, f), + MergedModuleDeclaration m => new SourceModuleSymbol(this.DeclaringCompilation, this, m), + GlobalDeclaration g when g.Syntax.FieldModifier is not null => new SourceFieldSymbol(this, g), + GlobalDeclaration g when g.Syntax.FieldModifier is null => new SourceAutoPropertySymbol(this, g), + ClassDeclaration c => new SourceClassSymbol(this, c), _ => throw new ArgumentOutOfRangeException(nameof(declaration)), }; - private SourceFunctionSymbol BuildFunction(FunctionDeclaration declaration) => new(this, declaration); - private SourceFieldSymbol BuildGlobalField(GlobalDeclaration declaration) => new(this, declaration); - - private IEnumerable BuildGlobalProperty(GlobalDeclaration declaration) - { - // Auto-property, need to add getter, setter and backing field - var prop = new SourceAutoPropertySymbol(this, declaration); - yield return prop; - if (prop.Getter is not null) yield return prop.Getter; - if (prop.Setter is not null) yield return prop.Setter; - yield return prop.BackingField; - } - - private SourceModuleSymbol BuildModule(MergedModuleDeclaration declaration) => new(this.DeclaringCompilation, this, declaration); - private SourceClassSymbol BuildClass(ClassDeclaration declaration) => new(this, declaration); - - private SymbolDocumentation BuildDocumentation() => - MarkdownDocumentationExtractor.Extract(this); + private SymbolDocumentation BuildDocumentation() => MarkdownDocumentationExtractor.Extract(this); } diff --git a/src/Draco.Compiler/Internal/Symbols/Symbol.cs b/src/Draco.Compiler/Internal/Symbols/Symbol.cs index 2e460c13f..c4d8453be 100644 --- a/src/Draco.Compiler/Internal/Symbols/Symbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Symbol.cs @@ -8,6 +8,7 @@ using Draco.Compiler.Internal.Documentation; using Draco.Compiler.Internal.Symbols.Generic; using Draco.Compiler.Internal.Symbols.Metadata; +using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Symbols.Synthetized; using Draco.Compiler.Internal.Utilities; @@ -332,15 +333,26 @@ private protected string GenericsToString() }; /// - /// Retrieves additional symbols for the given . + /// Retrieves additional symbols for the given symbol that should live in the same scope as the symbol itself. + /// This returns the constructor functions for types for example. /// /// The symbol to get additional symbols for. /// The additional symbols for the given . public static IEnumerable GetAdditionalSymbols(Symbol symbol) { - if (symbol is not TypeSymbol typeSymbol) return []; - if (typeSymbol.IsAbstract) return []; - // For other types we provide constructor functions - return typeSymbol.Constructors.Select(ctor => new ConstructorFunctionSymbol(ctor)); + switch (symbol) + { + case TypeSymbol typeSymbol: + if (typeSymbol.IsAbstract) yield break; + // For non-abstract types we provide constructor functions + foreach (var ctor in typeSymbol.Constructors) yield return new ConstructorFunctionSymbol(ctor); + break; + case SourceAutoPropertySymbol autoProp: + // For auto-properties we provide the backing field and the accessors in the same scope + if (autoProp.Getter is not null) yield return autoProp.Getter; + if (autoProp.Setter is not null) yield return autoProp.Setter; + yield return autoProp.BackingField; + break; + } } } From bb06a726e432d25a11a217672d686c9ada552e96 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sat, 2 Nov 2024 18:33:46 +0100 Subject: [PATCH 068/109] More simplification --- .../Symbols/Script/ScriptModuleSymbol.cs | 67 +++++++------------ .../Symbols/Source/SourceModuleSymbol.cs | 5 -- src/Draco.Compiler/Internal/Symbols/Symbol.cs | 4 +- 3 files changed, 29 insertions(+), 47 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs index 2a5380c82..89b1a65f8 100644 --- a/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs @@ -84,30 +84,26 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) // Non-declaration statements are compiled into an initializer method if (statement is not DeclarationStatementSyntax decl) continue; - // Build the symbol(s) - foreach (var member in this.BuildMember(decl.Declaration)) - { - var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); - result.Add(member); - - // We check for illegal shadowing - if (earlierMember is null) continue; - - // Overloading is legal - if (member is FunctionSymbol && earlierMember is FunctionSymbol) continue; - - // If the illegal member is special name, it was cascaded from a declaration with multiple symbols, - // like an autoprop, skip it - if (member.IsSpecialName) continue; - - // Illegal - var syntax = member.DeclaringSyntax; - Debug.Assert(syntax is not null); - binderProvider.DiagnosticBag.Add(Diagnostic.Create( - template: SymbolResolutionErrors.IllegalShadowing, - location: syntax.Location, - formatArgs: member.Name)); - } + var member = this.BuildMember(decl.Declaration); + if (member is null) continue; + + var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); + result.Add(member); + result.AddRange(GetAdditionalSymbols(member)); + + // We check for illegal shadowing + if (earlierMember is null) continue; + + // Overloading is legal + if (member is FunctionSymbol && earlierMember is FunctionSymbol) continue; + + // Illegal + var syntax = member.DeclaringSyntax; + Debug.Assert(syntax is not null); + binderProvider.DiagnosticBag.Add(Diagnostic.Create( + template: SymbolResolutionErrors.IllegalShadowing, + location: syntax.Location, + formatArgs: member.Name)); } // We add a function to evaluate the script @@ -137,28 +133,17 @@ private ScriptBinding BindScriptBindings(IBinderProvider binderProvider) return binder.BindScript(this, binderProvider.DiagnosticBag); } - private IEnumerable BuildMember(DeclarationSyntax decl) => decl switch + private Symbol? BuildMember(DeclarationSyntax decl) => decl switch { ImportDeclarationSyntax - or UnexpectedDeclarationSyntax => [], - FunctionDeclarationSyntax f => [this.BuildFunction(f)], - VariableDeclarationSyntax v when v.FieldModifier is not null => [this.BuildField(v)], - VariableDeclarationSyntax v when v.FieldModifier is null => this.BuildAutoProperty(v), - ModuleDeclarationSyntax m => [this.BuildModule(m)], + or UnexpectedDeclarationSyntax => null, + FunctionDeclarationSyntax f => new ScriptFunctionSymbol(this, f), + VariableDeclarationSyntax v when v.FieldModifier is not null => new ScriptFieldSymbol(this, v), + VariableDeclarationSyntax v when v.FieldModifier is null => new ScriptAutoPropertySymbol(this, v), + ModuleDeclarationSyntax m => this.BuildModule(m), _ => throw new ArgumentOutOfRangeException(nameof(decl)), }; - private ScriptFunctionSymbol BuildFunction(FunctionDeclarationSyntax syntax) => new(this, syntax); - private ScriptFieldSymbol BuildField(VariableDeclarationSyntax syntax) => new(this, syntax); - private IEnumerable BuildAutoProperty(VariableDeclarationSyntax syntax) - { - var property = new ScriptAutoPropertySymbol(this, syntax); - yield return property; - if (property.Getter is not null) yield return property.Getter; - if (property.Setter is not null) yield return property.Setter; - yield return property.BackingField; - } - private SourceModuleSymbol BuildModule(ModuleDeclarationSyntax syntax) { // We need to wrap it into a merged module declaration diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs index 664fce64c..337a54694 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs @@ -85,11 +85,6 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) // Overloading is legal if (member is FunctionSymbol && earlierMember is FunctionSymbol) continue; - // NOTE: An illegal shadowing can be caused by a property, which introduces additional synthetized symbols - // like the backing field - // We check for these synthetized symbols and if they are special-named, we ignore them - if (member.IsSpecialName) continue; - // Illegal var syntax = member.DeclaringSyntax; Debug.Assert(syntax is not null); diff --git a/src/Draco.Compiler/Internal/Symbols/Symbol.cs b/src/Draco.Compiler/Internal/Symbols/Symbol.cs index c4d8453be..05b0589a1 100644 --- a/src/Draco.Compiler/Internal/Symbols/Symbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Symbol.cs @@ -9,6 +9,7 @@ using Draco.Compiler.Internal.Symbols.Generic; using Draco.Compiler.Internal.Symbols.Metadata; using Draco.Compiler.Internal.Symbols.Source; +using Draco.Compiler.Internal.Symbols.Syntax; using Draco.Compiler.Internal.Symbols.Synthetized; using Draco.Compiler.Internal.Utilities; @@ -332,6 +333,7 @@ private protected string GenericsToString() _ => throw new InvalidOperationException($"illegal visibility modifier token {kind}"), }; + // TODO: We could have this as a base member for symbols /// /// Retrieves additional symbols for the given symbol that should live in the same scope as the symbol itself. /// This returns the constructor functions for types for example. @@ -347,7 +349,7 @@ public static IEnumerable GetAdditionalSymbols(Symbol symbol) // For non-abstract types we provide constructor functions foreach (var ctor in typeSymbol.Constructors) yield return new ConstructorFunctionSymbol(ctor); break; - case SourceAutoPropertySymbol autoProp: + case SyntaxAutoPropertySymbol autoProp: // For auto-properties we provide the backing field and the accessors in the same scope if (autoProp.Getter is not null) yield return autoProp.Getter; if (autoProp.Setter is not null) yield return autoProp.Setter; From 7072883be1ecbe3c92b83c90262ff57641152c68 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sat, 2 Nov 2024 18:40:21 +0100 Subject: [PATCH 069/109] Placed additional symbols into respective class --- .../Metadata/MetadataNamespaceSymbol.cs | 2 +- .../Metadata/MetadataStaticClassSymbol.cs | 2 +- .../Symbols/Metadata/MetadataTypeSymbol.cs | 2 +- .../Symbols/Script/ScriptModuleSymbol.cs | 2 +- .../Symbols/Source/SourceModuleSymbol.cs | 2 +- src/Draco.Compiler/Internal/Symbols/Symbol.cs | 24 +++---------------- .../Syntax/SyntaxAutoPropertySymbol.cs | 9 +++++++ .../Internal/Symbols/TypeSymbol.cs | 8 +++++++ 8 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs index 3c455a260..805f7e2b8 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataNamespaceSymbol.cs @@ -57,7 +57,7 @@ private ImmutableArray BuildMembers() var symbol = MetadataSymbol.ToSymbol(this, typeDef); result.Add(symbol); // Add additional symbols - result.AddRange(GetAdditionalSymbols(symbol)); + result.AddRange(symbol.GetAdditionalSymbols()); } // Done diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs index c8e44672b..066379ad9 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataStaticClassSymbol.cs @@ -67,7 +67,7 @@ private ImmutableArray BuildMembers() var symbol = MetadataSymbol.ToSymbol(this, typeDef); result.Add(symbol); // Add additional symbols - result.AddRange(GetAdditionalSymbols(symbol)); + result.AddRange(symbol.GetAdditionalSymbols()); } // Methods diff --git a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs index c3cd96f10..022b03bf3 100644 --- a/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Metadata/MetadataTypeSymbol.cs @@ -156,7 +156,7 @@ private ImmutableArray BuildMembers() var symbol = MetadataSymbol.ToSymbol(this, typeDef); result.Add(symbol); // Add additional symbols - result.AddRange(GetAdditionalSymbols(symbol)); + result.AddRange(symbol.GetAdditionalSymbols()); } // Methods diff --git a/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs index 89b1a65f8..612e7a283 100644 --- a/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Script/ScriptModuleSymbol.cs @@ -89,7 +89,7 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); result.Add(member); - result.AddRange(GetAdditionalSymbols(member)); + result.AddRange(member.GetAdditionalSymbols()); // We check for illegal shadowing if (earlierMember is null) continue; diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs index 337a54694..a35e2264a 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceModuleSymbol.cs @@ -77,7 +77,7 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) { var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); result.Add(member); - result.AddRange(GetAdditionalSymbols(member)); + result.AddRange(member.GetAdditionalSymbols()); // We check for illegal shadowing if (earlierMember is null) continue; diff --git a/src/Draco.Compiler/Internal/Symbols/Symbol.cs b/src/Draco.Compiler/Internal/Symbols/Symbol.cs index 05b0589a1..0819db402 100644 --- a/src/Draco.Compiler/Internal/Symbols/Symbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Symbol.cs @@ -333,28 +333,10 @@ private protected string GenericsToString() _ => throw new InvalidOperationException($"illegal visibility modifier token {kind}"), }; - // TODO: We could have this as a base member for symbols /// - /// Retrieves additional symbols for the given symbol that should live in the same scope as the symbol itself. + /// Retrieves additional symbols for this symbol that should live in the same scope as this symbol itself. /// This returns the constructor functions for types for example. /// - /// The symbol to get additional symbols for. - /// The additional symbols for the given . - public static IEnumerable GetAdditionalSymbols(Symbol symbol) - { - switch (symbol) - { - case TypeSymbol typeSymbol: - if (typeSymbol.IsAbstract) yield break; - // For non-abstract types we provide constructor functions - foreach (var ctor in typeSymbol.Constructors) yield return new ConstructorFunctionSymbol(ctor); - break; - case SyntaxAutoPropertySymbol autoProp: - // For auto-properties we provide the backing field and the accessors in the same scope - if (autoProp.Getter is not null) yield return autoProp.Getter; - if (autoProp.Setter is not null) yield return autoProp.Setter; - yield return autoProp.BackingField; - break; - } - } + /// The additional symbols for this symbol. + protected internal virtual IEnumerable GetAdditionalSymbols() => []; } diff --git a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxAutoPropertySymbol.cs b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxAutoPropertySymbol.cs index 830deefc3..d940920e7 100644 --- a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxAutoPropertySymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxAutoPropertySymbol.cs @@ -8,6 +8,7 @@ using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Utilities; using Draco.Compiler.Internal.Symbols.Synthetized.AutoProperty; +using System.Collections.Generic; namespace Draco.Compiler.Internal.Symbols.Syntax; @@ -63,4 +64,12 @@ private SymbolDocumentation BuildDocumentation() => private FunctionSymbol BuildGetter() => new AutoPropertyGetterSymbol(this.ContainingSymbol, this); private FunctionSymbol? BuildSetter() => new AutoPropertySetterSymbol(this.ContainingSymbol, this); private FieldSymbol BuildBackingField() => new AutoPropertyBackingFieldSymbol(this.ContainingSymbol, this); + + protected internal override sealed IEnumerable GetAdditionalSymbols() + { + // For auto-properties we provide the backing field and the accessors in the same scope + if (this.Getter is not null) yield return this.Getter; + if (this.Setter is not null) yield return this.Setter; + yield return this.BackingField; + } } diff --git a/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs b/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs index b0b782bac..b23fdd510 100644 --- a/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/TypeSymbol.cs @@ -4,6 +4,7 @@ using System.Linq; using Draco.Compiler.Api.Semantics; using Draco.Compiler.Internal.Symbols.Generic; +using Draco.Compiler.Internal.Symbols.Synthetized; using Draco.Compiler.Internal.Utilities; namespace Draco.Compiler.Internal.Symbols; @@ -213,4 +214,11 @@ public override TypeSymbol GenericInstantiate(Symbol? containingSymbol, GenericC public override TResult Accept(SymbolVisitor visitor) => visitor.VisitType(this); public override abstract string ToString(); + + protected internal override sealed IEnumerable GetAdditionalSymbols() + { + if (this.IsAbstract) yield break; + // For non-abstract types we provide constructor functions + foreach (var ctor in this.Constructors) yield return new ConstructorFunctionSymbol(ctor); + } } From 9482eba0ae8d0cb6f72d89d1332cabcfe8b6ce48 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 15:03:02 +0100 Subject: [PATCH 070/109] Update SyntaxFactory.cs --- src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs index d783fba93..0db8a485b 100644 --- a/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs +++ b/src/Draco.Compiler/Api/Syntax/SyntaxFactory.cs @@ -245,7 +245,11 @@ public static VariableDeclarationSyntax VarDeclaration( attributes: [], visibility: visibility, isGlobal: false, - false, true, name, type, value); + isField: false, + isMutable: true, + name: name, + type: type, + value: value); public static VariableDeclarationSyntax FieldValDeclaration( Visibility? visibility, From 6f3ae6941383474d5dac3e4600df35fa003506bf Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 15:06:11 +0100 Subject: [PATCH 071/109] Update ErrorThisParameterSymbol.cs --- .../Internal/Symbols/Error/ErrorThisParameterSymbol.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs index caa5aa23b..e5c4e6631 100644 --- a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs @@ -1,12 +1,14 @@ namespace Draco.Compiler.Internal.Symbols.Error; /// -/// An error this parameter symbol. +/// An 'this' parameter symbol where it's invalid. /// -/// -/// -internal sealed class ErrorThisParameterSymbol(TypeSymbol type, FunctionSymbol containingSymbol) : ParameterSymbol +internal sealed class ErrorThisParameterSymbol( + TypeSymbol type, + FunctionSymbol containingSymbol) : ParameterSymbol { public override TypeSymbol Type { get; } = type; public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; + + public override bool IsError => true; } From 5c491940c85b0c25d7dfcf39abb75c9b66ff2c1a Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 15:06:39 +0100 Subject: [PATCH 072/109] Update ErrorThisParameterSymbol.cs --- .../Internal/Symbols/Error/ErrorThisParameterSymbol.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs index e5c4e6631..6cfb35ddf 100644 --- a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs @@ -1,7 +1,7 @@ namespace Draco.Compiler.Internal.Symbols.Error; /// -/// An 'this' parameter symbol where it's invalid. +/// A 'this' parameter symbol where it's invalid. /// internal sealed class ErrorThisParameterSymbol( TypeSymbol type, From 312be232cc2480fb373c00ce7e868546f9718d66 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 16:10:25 +0100 Subject: [PATCH 073/109] Tweaks --- .../Internal/Symbols/Error/ErrorThisParameterSymbol.cs | 1 + src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs | 7 ------- src/Draco.Compiler/Internal/Symbols/IMemberSymbol.cs | 2 +- src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs | 6 +++++- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs index 6cfb35ddf..437738938 100644 --- a/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Error/ErrorThisParameterSymbol.cs @@ -11,4 +11,5 @@ internal sealed class ErrorThisParameterSymbol( public override FunctionSymbol ContainingSymbol { get; } = containingSymbol; public override bool IsError => true; + public override bool IsThis => true; } diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index 77ebd1a0c..c8598c0a7 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -75,13 +75,6 @@ public delegate IOperand CodegenDelegate( _ => throw new System.ArgumentOutOfRangeException(nameof(token)), }; - /// - /// The receiver of this function, if it has one. - /// - public TypeSymbol? ReceiverType => this.IsStatic - ? null - : this.ContainingSymbol as TypeSymbol; - /// /// The parameters of this function. /// diff --git a/src/Draco.Compiler/Internal/Symbols/IMemberSymbol.cs b/src/Draco.Compiler/Internal/Symbols/IMemberSymbol.cs index 9dede0337..d02ce1ea5 100644 --- a/src/Draco.Compiler/Internal/Symbols/IMemberSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/IMemberSymbol.cs @@ -6,7 +6,7 @@ namespace Draco.Compiler.Internal.Symbols; internal interface IMemberSymbol { /// - /// Specifying if given symbol is static. + /// Specifying if the given symbol is static. /// public bool IsStatic { get; } diff --git a/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs index d2968d14b..a238c7279 100644 --- a/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/ParameterSymbol.cs @@ -17,9 +17,13 @@ internal abstract partial class ParameterSymbol : LocalSymbol /// public virtual bool IsVariadic => false; + /// + /// True, if this is a 'this' (receiver) parameter. + /// + public virtual bool IsThis => false; + public override bool IsMutable => false; - public virtual bool IsThis => false; // NOTE: Override for covariant return type public override ParameterSymbol? GenericDefinition => null; public override SymbolKind Kind => SymbolKind.Parameter; From 5d3284292d122d10664e9635cf121b39fd293780 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 16:13:29 +0100 Subject: [PATCH 074/109] Update SemanticModel.cs --- src/Draco.Compiler/Api/Semantics/SemanticModel.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Api/Semantics/SemanticModel.cs b/src/Draco.Compiler/Api/Semantics/SemanticModel.cs index e239b9342..62f39ceb8 100644 --- a/src/Draco.Compiler/Api/Semantics/SemanticModel.cs +++ b/src/Draco.Compiler/Api/Semantics/SemanticModel.cs @@ -195,11 +195,12 @@ public ImmutableArray GetAllAccessibleSymbols(SyntaxNode? node) } case SourceClassSymbol classSymbol: { + // Could be the class itself if (classSymbol.DeclaringSyntax == syntax) return containingSymbol; + // Search for the corresponding syntax var symbol = classSymbol.Members .SingleOrDefault(sym => sym.DeclaringSyntax == syntax); - return symbol; } default: From 37c5f9a1e1061a685afaaf8b4f1f1013e81d4eb3 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 16:20:55 +0100 Subject: [PATCH 075/109] Update Binder_Expression.cs --- .../Internal/Binding/Binder_Expression.cs | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index bbc0ddbf5..a6a9d5f2d 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -711,40 +711,50 @@ private async BindingTask BindIndexExpression(IndexExpressionSy // Array getter return new BoundArrayAccessExpression(syntax, receiver, await BindingTask.WhenAll(argsTask)); } - return new BoundIndexGetExpression(syntax, receiver, indexer, await BindingTask.WhenAll(argsTask)); + else + { + // Any other indexer + return new BoundIndexGetExpression(syntax, receiver, indexer, await BindingTask.WhenAll(argsTask)); + } } private BindingTask BindThisExpression(ThisExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) { - if (this.ContainingSymbol is not SyntaxFunctionSymbol function || this.ContainingSymbol == null) + // Check, if we are in a function + if (this.ContainingSymbol is not SyntaxFunctionSymbol function) { + // No, report error diagnostics.Add(Diagnostic.Create( template: SymbolResolutionErrors.IllegalThis, - location: syntax.Location - )); + location: syntax.Location)); return BindingTask.FromResult( new BoundParameterExpression( syntax, new ErrorThisParameterSymbol(WellKnownTypes.ErrorType, new ErrorFunctionSymbol(0)))); } + // Check, if the function has a this argument var thisArg = function.ThisArgument; - if (thisArg is not null) + if (thisArg is null) { - var boundThis = new BoundParameterExpression(syntax, thisArg); - return BindingTask.FromResult(boundThis); - } - - diagnostics.Add(Diagnostic.Create( + // No, report error + diagnostics.Add(Diagnostic.Create( template: SymbolResolutionErrors.NoThisInStaticMethod, location: syntax.Location, formatArgs: [this.ContainingSymbol!.Name])); - var type = function.ContainingSymbol as TypeSymbol ?? WellKnownTypes.ErrorType; - return BindingTask.FromResult( - new BoundParameterExpression( - syntax, - new ErrorThisParameterSymbol(type, function))); + // We can approximate the type of the this argument by checking the containing type + var type = function.ContainingSymbol as TypeSymbol + ?? WellKnownTypes.ErrorType; + return BindingTask.FromResult( + new BoundParameterExpression( + syntax, + new ErrorThisParameterSymbol(type, function))); + } + + // All ok + var boundThis = new BoundParameterExpression(syntax, thisArg); + return BindingTask.FromResult(boundThis); } private async BindingTask BindGenericExpression(GenericExpressionSyntax syntax, ConstraintSolver constraints, DiagnosticBag diagnostics) @@ -877,13 +887,16 @@ private BindingTask WrapFunctions( return BindingTask.FromResult( new BoundDelegateCreationExpression(syntax, receiver, functions[0], delegateCtor)); } - // TODO: We should construct some constraints to resolve which one - // For now we report an error to not crash tools - diagnostics.Add(Diagnostic.Create( - template: TypeCheckingErrors.IllegalExpression, - location: syntax.Location)); - return BindingTask.FromResult( - new BoundReferenceErrorExpression(syntax, WellKnownTypes.ErrorType)); + else + { + // TODO: We should construct some constraints to resolve which one + // For now we report an error to not crash tools + diagnostics.Add(Diagnostic.Create( + template: TypeCheckingErrors.IllegalExpression, + location: syntax.Location)); + return BindingTask.FromResult( + new BoundReferenceErrorExpression(syntax, WellKnownTypes.ErrorType)); + } } } From a32b6c7b395bb23ea24d1ff77cff0c38e5aee2f6 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 16:39:31 +0100 Subject: [PATCH 076/109] Update SourceClassSymbol.cs --- .../Symbols/Source/SourceClassSymbol.cs | 78 +++++++++++-------- 1 file changed, 47 insertions(+), 31 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index de4062247..39ba623e0 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -19,26 +19,27 @@ internal sealed class SourceClassSymbol( Symbol containingSymbol, ClassDeclarationSyntax syntax) : TypeSymbol, ISourceSymbol { - public override ImmutableArray GenericParameters => this.BindGenericParametersIfNeeded(this.DeclaringCompilation!); + public override Symbol ContainingSymbol { get; } = containingSymbol; + public override ClassDeclarationSyntax DeclaringSyntax { get; } = syntax; + public override string Name => this.DeclaringSyntax.Name.Text; + + public override ImmutableArray GenericParameters => + this.BindGenericParametersIfNeeded(this.DeclaringCompilation!); private ImmutableArray genericParameters; - public override IEnumerable DefinedMembers => this.BindMembersIfNeeded(this.DeclaringCompilation!); + public override IEnumerable DefinedMembers => + this.BindMembersIfNeeded(this.DeclaringCompilation!); private ImmutableArray definedMembers; - public SourceClassSymbol(Symbol containingSymbol, ClassDeclaration declaration) : this(containingSymbol, declaration.Syntax) + public SourceClassSymbol(Symbol containingSymbol, ClassDeclaration declaration) + : this(containingSymbol, declaration.Syntax) { } - public override Symbol ContainingSymbol { get; } = containingSymbol; - public override string Name => this.DeclaringSyntax.Name.Text; - - public override ClassDeclarationSyntax DeclaringSyntax => syntax; - public void Bind(IBinderProvider binderProvider) { this.BindGenericParametersIfNeeded(binderProvider); this.BindMembersIfNeeded(binderProvider); - } private ImmutableArray BindGenericParametersIfNeeded(IBinderProvider binderProvider) => @@ -73,36 +74,51 @@ private ImmutableArray BindGenericParameters(IBinderProvide private ImmutableArray BindMembersIfNeeded(IBinderProvider binderProvider) => InterlockedUtils.InitializeDefault(ref this.definedMembers, () => this.BindMembers(binderProvider)); - private ImmutableArray BindMembers(IBinderProvider binder) + // TODO: This shadowing check logic is duplicated a few places + // Along with member construction, maybe factor it out + private ImmutableArray BindMembers(IBinderProvider binderProvider) { + // If there is no body, we only have a default constructor if (this.DeclaringSyntax.Body is EmptyClassBodySyntax) return [new DefaultConstructorSymbol(this)]; - var bodyClass = this.DeclaringSyntax.Body as BlockClassBodySyntax; - Debug.Assert(bodyClass is not null); - var declarationsSyntaxes = bodyClass.Declarations.ToList(); - var members = ImmutableArray.CreateBuilder(declarationsSyntaxes.Count + 1); - members.Add(new DefaultConstructorSymbol(this)); - foreach (var declarationSyntax in declarationsSyntaxes) + if (this.DeclaringSyntax.Body is BlockClassBodySyntax blockBody) { - var member = this.BindDeclaration(binder, declarationSyntax); - members.Add(member); + var result = ImmutableArray.CreateBuilder(); + // NOTE: For now we always add a default constructor + result.Add(new DefaultConstructorSymbol(this)); + foreach (var member in blockBody.Declarations.Select(this.BuildMember)) + { + var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); + result.Add(member); + result.AddRange(member.GetAdditionalSymbols()); + + // We check for illegal shadowing + if (earlierMember is null) continue; + + // Overloading is legal + if (member is FunctionSymbol && earlierMember is FunctionSymbol) continue; + + // Illegal + var syntax = member.DeclaringSyntax; + Debug.Assert(syntax is not null); + binderProvider.DiagnosticBag.Add(Diagnostic.Create( + template: SymbolResolutionErrors.IllegalShadowing, + location: syntax.Location, + formatArgs: member.Name)); + } + return result.ToImmutable(); } - return members.ToImmutable(); + + return []; } - private Symbol BindDeclaration(IBinderProvider binder, DeclarationSyntax declarationSyntax) + private Symbol BuildMember(DeclarationSyntax syntax) => syntax switch { - switch (declarationSyntax) - { - case FunctionDeclarationSyntax functionSyntax: - return new SourceFunctionSymbol(this, functionSyntax); - case VariableDeclarationSyntax fieldSyntax: - if (fieldSyntax.FieldModifier is null) throw new NotImplementedException(); - return new SourceFieldSymbol(this, fieldSyntax); - default: - throw new NotImplementedException(); // TODO implement this - } - } + FunctionDeclarationSyntax functionSyntax => new SourceFunctionSymbol(this, functionSyntax), + VariableDeclarationSyntax varSyntax when varSyntax.FieldModifier is null => new SourceAutoPropertySymbol(this, varSyntax), + VariableDeclarationSyntax varSyntax when varSyntax.FieldModifier is not null => new SourceFieldSymbol(this, varSyntax), + _ => throw new NotImplementedException(), // TODO implement this + }; public override string ToString() => $"{this.Name}{this.GenericsToString()}"; } From ff3636c8c4d5cf64810adf886d8376e27681e85c Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 16:43:15 +0100 Subject: [PATCH 077/109] Update ClassBinder.cs --- src/Draco.Compiler/Internal/Binding/ClassBinder.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs index b9bf7a5de..8a0492f49 100644 --- a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -6,6 +6,9 @@ namespace Draco.Compiler.Internal.Binding; +/// +/// Binds an in-source defined class. +/// internal sealed class ClassBinder(Binder parent, TypeSymbol symbol) : Binder(parent) { public override TypeSymbol ContainingSymbol => this.symbol; @@ -32,7 +35,7 @@ internal override void LookupLocal(LookupResult result, string name, ref LookupF if (member.Name != name) continue; if (!allowSymbol(member)) continue; result.Add(member); - break; + // NOTE: We don't break here, because there are potentially multiple overloads } } } From 3178f1b19414e2f0fc2d4ed09ba73b04783a00d0 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 16:47:17 +0100 Subject: [PATCH 078/109] Update ClassBinder.cs --- src/Draco.Compiler/Internal/Binding/ClassBinder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs index 8a0492f49..cf83df1ed 100644 --- a/src/Draco.Compiler/Internal/Binding/ClassBinder.cs +++ b/src/Draco.Compiler/Internal/Binding/ClassBinder.cs @@ -17,7 +17,6 @@ internal sealed class ClassBinder(Binder parent, TypeSymbol symbol) : Binder(par private readonly TypeSymbol symbol = symbol; public override IEnumerable DeclaredSymbols => this.symbol.Members - .Cast() .Concat(this.symbol.GenericParameters); internal override void LookupLocal(LookupResult result, string name, ref LookupFlags flags, Predicate allowSymbol, SyntaxNode? currentReference) From 91db04d69ba74cfa75371d87da5347b049574c83 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 17:41:50 +0100 Subject: [PATCH 079/109] Simplified --- .../Internal/Binding/Binder_Expression.cs | 2 +- .../Symbols/Source/SourceFunctionSymbol.cs | 3 +- .../Symbols/Syntax/SyntaxFunctionSymbol.cs | 51 ++++++++++--------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index a6a9d5f2d..638991f1f 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -734,7 +734,7 @@ private BindingTask BindThisExpression(ThisExpressionSyntax syn } // Check, if the function has a this argument - var thisArg = function.ThisArgument; + var thisArg = function.ThisParameter; if (thisArg is null) { // No, report error diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs index b743878bc..5c3b9bf32 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceFunctionSymbol.cs @@ -27,12 +27,11 @@ public SourceFunctionSymbol(Symbol containingSymbol, FunctionDeclaration declara { } - public override bool IsStatic => this.ThisArgument == null; - public override void Bind(IBinderProvider binderProvider) { this.BindAttributesIfNeeded(binderProvider); this.BindGenericParametersIfNeeded(binderProvider); + this.BindThisParameterIfNeeded(binderProvider); this.BindParametersIfNeeded(binderProvider); // Force binding of parameters, as the type is lazy too foreach (var param in this.Parameters.Cast()) param.Bind(binderProvider); diff --git a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs index 2ba7d9626..d63a029be 100644 --- a/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Syntax/SyntaxFunctionSymbol.cs @@ -22,6 +22,7 @@ internal abstract class SyntaxFunctionSymbol( public override Symbol ContainingSymbol => containingSymbol; public override FunctionDeclarationSyntax DeclaringSyntax => syntax; public override string Name => this.DeclaringSyntax.Name.Text; + public override bool IsStatic => this.ThisParameter is null; public override Api.Semantics.Visibility Visibility => GetVisibilityFromTokenKind(this.DeclaringSyntax.VisibilityModifier?.Kind); @@ -35,15 +36,11 @@ internal abstract class SyntaxFunctionSymbol( public override ImmutableArray Parameters => this.BindParametersIfNeeded(this.DeclaringCompilation!); private ImmutableArray parameters; - public SourceThisParameterSymbol? ThisArgument - { - get - { - this.BindParametersIfNeeded(this.DeclaringCompilation!); - return this.thisArgument; - } - } - private SourceThisParameterSymbol? thisArgument; + /// + /// An optional this parameter, if the function is an instance method. + /// + public ParameterSymbol? ThisParameter => this.BindThisParameterIfNeeded(this.DeclaringCompilation!); + private ParameterSymbol? thisParameter; public override TypeSymbol ReturnType => this.BindReturnTypeIfNeeded(this.DeclaringCompilation!); private TypeSymbol? returnType; @@ -101,6 +98,16 @@ private ImmutableArray BindGenericParameters(IBinderProvide return genericParams.ToImmutable(); } + protected ParameterSymbol? BindThisParameterIfNeeded(IBinderProvider binderProvider) => + InterlockedUtils.InitializeMaybeNull(ref this.thisParameter, () => this.BindThisParameter(binderProvider)); + + private ParameterSymbol? BindThisParameter(IBinderProvider binderProvider) + { + if (this.DeclaringSyntax.ParameterList.Values.FirstOrDefault() is not ThisParameterSyntax thisSyntax) return null; + + return new SourceThisParameterSymbol(this, thisSyntax); + } + protected ImmutableArray BindParametersIfNeeded(IBinderProvider binderProvider) => InterlockedUtils.InitializeDefault(ref this.parameters, () => this.BindParameters(binderProvider)); @@ -109,29 +116,25 @@ private ImmutableArray BindParameters(IBinderProvider binderPro var parameterSyntaxes = this.DeclaringSyntax.ParameterList.Values.ToList(); var parameters = ImmutableArray.CreateBuilder(); - var isInstance = null as SourceThisParameterSymbol; - - for (var i = 0; i < parameterSyntaxes.Count; ++i) + // NOTE: If the first parameter is 'this', we skip it + var start = parameterSyntaxes.FirstOrDefault() is ThisParameterSyntax ? 1 : 0; + for (var i = start; i < parameterSyntaxes.Count; ++i) { var syntax = parameterSyntaxes[i]; - - if (syntax is ThisParameterSyntax thisParameter) + if (syntax is ThisParameterSyntax thisSyntax) { - var asSymbol = new SourceThisParameterSymbol(this, thisParameter); - if (i == 0) - { - this.thisArgument = asSymbol; - isInstance = asSymbol; - continue; - } + // NOTE: Do we want to construct an error here, or regular symbol is fine? + // Error, 'this' at an illegal place + var thisSymbol = new SourceThisParameterSymbol(this, thisSyntax); + parameters.Add(thisSymbol); binderProvider.DiagnosticBag.Add(Diagnostic.Create( template: SymbolResolutionErrors.ThisParameterNotFirst, - location: thisParameter.Location)); - parameters.Add(asSymbol); + location: thisSyntax.Location)); continue; } - var parameterSyntax = (NormalParameterSyntax)syntax; + // We assume it's a regular parameter + var parameterSyntax = (NormalParameterSyntax)syntax; var parameterName = parameterSyntax.Name.Text; var usedBefore = parameters.Any(p => p.Name == parameterName); From 498fd589b3fbbdb5ee4df8ad3649bb90fb8886b3 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Sun, 3 Nov 2024 17:43:41 +0100 Subject: [PATCH 080/109] Update BinderCache.cs --- src/Draco.Compiler/Internal/Binding/BinderCache.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/Binding/BinderCache.cs b/src/Draco.Compiler/Internal/Binding/BinderCache.cs index 50ab5d131..f0fc11a01 100644 --- a/src/Draco.Compiler/Internal/Binding/BinderCache.cs +++ b/src/Draco.Compiler/Internal/Binding/BinderCache.cs @@ -99,7 +99,8 @@ private ClassBinder BuildClassDeclarationBinder(ClassDeclarationSyntax syntax) { Debug.Assert(syntax.Parent is not null); var binder = this.GetBinder(syntax.Parent); - + // Search for the function in the parents container + // For that we unwrap from the injected import layer(s) var parent = UnwrapFromImportBinder(binder); var classSymbol = parent.DeclaredSymbols .OfType() From b10833ebacb139ea12d59cc49ba63a5d47c22df5 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 13:52:44 +0100 Subject: [PATCH 081/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 53 +++++++------------ 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 06c064c03..9ac93c9c1 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -95,8 +95,6 @@ public static void Generate( private readonly IAssembly assembly; private readonly BlobBuilder ilBuilder = new(); - private readonly Dictionary moduleReferenceHandles = []; - private readonly Dictionary intrinsicReferenceHandles = []; private readonly AssemblyReferenceHandle systemRuntimeReference; private readonly TypeReferenceHandle systemObjectReference; private readonly TypeReferenceHandle systemValueTypeReference; @@ -154,31 +152,8 @@ private void WriteModuleAndAssemblyDefinition() methodList: MetadataTokens.MethodDefinitionHandle(1)); } - public TypeReferenceHandle GetModuleReferenceHandle(IModule module) - { - if (!this.moduleReferenceHandles.TryGetValue(module, out var handle)) - { - var resolutionScope = module.Parent is null - // Root module, we take the module definition containing it - ? (EntityHandle)this.ModuleDefinitionHandle - // We take its parent module - : this.GetModuleReferenceHandle(module.Parent); - var name = string.IsNullOrEmpty(module.Name) - ? CompilerConstants.DefaultModuleName - : module.Name; - handle = this.GetOrAddTypeReference( - parent: resolutionScope, - @namespace: null, - name: name); - this.moduleReferenceHandles.Add(module, handle); - } - return handle; - } - public UserStringHandle GetStringLiteralHandle(string text) => this.MetadataBuilder.GetOrAddUserString(text); - public MemberReferenceHandle GetIntrinsicReferenceHandle(Symbol symbol) => this.intrinsicReferenceHandles[symbol]; - // TODO: This can be cached by symbol to avoid double reference instertion public EntityHandle GetEntityHandle(Symbol symbol) { @@ -279,7 +254,7 @@ Symbol GetContainingSymbol() // Probably not, let's shove them somewhere known once we can make up our minds // This is the case for synthetized ctor functions for example parent: func.ContainingSymbol is null - ? this.GetModuleReferenceHandle(this.assembly.RootModule) + ? (EntityHandle)this.ModuleDefinitionHandle : this.GetEntityHandle(GetContainingSymbol()), name: func.NestedName, signature: this.EncodeBlob(e => @@ -302,15 +277,25 @@ Symbol GetContainingSymbol() case SourceModuleSymbol: case ScriptModuleSymbol: { - if (this.RedirectHandlesToCompileTimeRoot) - { - var root = this.Compilation.CompileTimeExecutor.RootModule; - return this.GetModuleReferenceHandle(root); - } + var moduleSymbol = this.RedirectHandlesToCompileTimeRoot + ? this.Compilation.RootModule + : (ModuleSymbol)symbol; + var parent = moduleSymbol.AncestorChain + .Skip(1) + .FirstOrDefault(s => s is TypeSymbol or ModuleSymbol); - var module = (ModuleSymbol)symbol; - var irModule = this.assembly.Lookup(module); - return this.GetModuleReferenceHandle(irModule); + var resolutionScope = parent is null + // Root module, we take the module definition containing it + ? (EntityHandle)this.ModuleDefinitionHandle + // We take its parent module + : this.GetEntityHandle(parent); + var name = string.IsNullOrEmpty(moduleSymbol.Name) + ? CompilerConstants.DefaultModuleName + : moduleSymbol.Name; + return this.GetOrAddTypeReference( + parent: resolutionScope, + @namespace: null, + name: name); } case FieldSymbol field: From 8d7c65b7eaafb23b980ad920baa4ea3294aa65a8 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:06:14 +0100 Subject: [PATCH 082/109] Update MetadataCodegen.cs --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 9ac93c9c1..0fb2fe6a5 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -226,12 +226,9 @@ Symbol GetContainingSymbol() { // We can't have nested functions represented in metadata directly, so we'll climb up the parent chain // To find the first non-function container - var current = func.ContainingSymbol; - while (current is FunctionSymbol func) - { - current = func.ContainingSymbol; - } - return current!; + return func.AncestorChain + .Skip(1) + .First(s => s is not FunctionSymbol); } if (func.ContainingSymbol is not TypeSymbol type) return func.ContainingSymbol!; From f46bb86416f4dccd78887ffd8b1009a0f662cb7f Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:11:30 +0100 Subject: [PATCH 083/109] Update ModelExtensions.cs --- .../OptimizingIr/Model/ModelExtensions.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/ModelExtensions.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/ModelExtensions.cs index 872ab3a75..220b736b1 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/ModelExtensions.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/ModelExtensions.cs @@ -9,23 +9,6 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; /// internal static class ModelExtensions { - /// - /// Looks up the module in an assembly based on the module symbol. - /// - /// The assembly to lookup in. - /// The module to look up. - /// The looked up module within . - public static IModule Lookup(this IAssembly assembly, ModuleSymbol module) - { - if (ReferenceEquals(assembly.RootModule.Symbol, module)) return assembly.RootModule; - if (module.ContainingSymbol is not ModuleSymbol containingModule) - { - throw new KeyNotFoundException("the module could not be resolved based on the symbol"); - } - var parentModule = Lookup(assembly, containingModule); - return parentModule.Submodules[module]; - } - /// /// Retrieves all functions that are statically referenced by a given procedure. /// From 06dad340a7afb52e7709dadf4a1e7028756a55e0 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:19:19 +0100 Subject: [PATCH 084/109] Update Procedure.cs --- src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index da4e14c54..3bd292fa4 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -14,7 +14,6 @@ internal sealed class Procedure : IProcedure { public FunctionSymbol Symbol { get; } public string Name => this.Symbol.NestedName; - public TypeSymbol? TypeSymbol => this.Symbol.Type; public Module DeclaringModule { get; } IModule IProcedure.DeclaringModule => this.DeclaringModule; public Class? DeclaringType { get; } From 01ae05d2b6d73442ec31fdf03143d947ee92254b Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:27:38 +0100 Subject: [PATCH 085/109] Removed parent relationships --- .../Internal/OptimizingIr/Model/Assembly.cs | 28 ++----------------- .../Internal/OptimizingIr/Model/Class.cs | 9 ++---- .../Internal/OptimizingIr/Model/IClass.cs | 10 ------- .../Internal/OptimizingIr/Model/IModule.cs | 10 ------- .../Internal/OptimizingIr/Model/IProcedure.cs | 16 ----------- .../Internal/OptimizingIr/Model/Module.cs | 16 +++-------- .../Internal/OptimizingIr/Model/Procedure.cs | 10 +------ 7 files changed, 10 insertions(+), 89 deletions(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Assembly.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Assembly.cs index b32136f51..10875a7fa 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Assembly.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Assembly.cs @@ -7,29 +7,12 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; /// /// A mutable implementation. /// -internal sealed class Assembly : IAssembly +internal sealed class Assembly(ModuleSymbol module) : IAssembly { - private Procedure? entryPoint; - private readonly Module rootModule; + private readonly Module rootModule = new(module); public string Name { get; set; } = "output"; - public Procedure? EntryPoint - { - get => this.entryPoint; - set - { - if (value is null) - { - this.entryPoint = null; - return; - } - if (!ReferenceEquals(this, value.Assembly)) - { - throw new System.InvalidOperationException("entry point must be part of the assembly"); - } - this.entryPoint = value; - } - } + public Procedure? EntryPoint { get; set; } IProcedure? IAssembly.EntryPoint => this.EntryPoint; public Module RootModule => this.rootModule; @@ -37,11 +20,6 @@ public Procedure? EntryPoint public ImmutableArray GetAllProcedures() => this.rootModule.GetProcedures(); - public Assembly(ModuleSymbol module) - { - this.rootModule = new Module(module, this, null); - } - public override string ToString() { var result = new StringBuilder(); diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs index c348fcae4..be78a006d 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs @@ -6,17 +6,12 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; -internal sealed class Class(Module declaringModule, TypeSymbol symbol) : IClass +internal sealed class Class(TypeSymbol symbol) : IClass { public TypeSymbol Symbol { get; } = symbol; public string Name => this.Symbol.Name; - public Module DeclaringModule { get; } = declaringModule; - IModule IClass.DeclaringModule => this.DeclaringModule; - public Assembly Assembly => this.DeclaringModule.Assembly; - IAssembly IClass.Assembly => this.Assembly; - public IReadOnlyList Generics => this.Symbol.GenericParameters; public IReadOnlyDictionary Methods => this.methods; public IReadOnlyList Fields => InterlockedUtils.InitializeDefault( @@ -30,7 +25,7 @@ public Procedure DefineMethod(FunctionSymbol functionSymbol) { if (!this.methods.TryGetValue(functionSymbol, out var result)) { - result = new Procedure(this.DeclaringModule, this, functionSymbol); + result = new Procedure(functionSymbol); this.methods.Add(functionSymbol, result); } return (Procedure)result; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index 018425cde..f145cef73 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -18,16 +18,6 @@ internal interface IClass /// public string Name { get; } - /// - /// The module this type is defined in. - /// - public IModule DeclaringModule { get; } - - /// - /// The assembly this type is defined in. - /// - public IAssembly Assembly { get; } - /// /// The generic parameters on this type. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs index 8831d2d7e..1fbb29f15 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IModule.cs @@ -18,16 +18,6 @@ internal interface IModule /// public string Name { get; } - /// - /// The assembly this module is defined in. - /// - public IAssembly Assembly { get; } - - /// - /// The parent module of this module. - /// - public IModule? Parent { get; } - /// /// The submodules of this module. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs index b8efd914b..dc28f9114 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IProcedure.cs @@ -23,22 +23,6 @@ internal interface IProcedure /// public string Name { get; } - /// - /// The type this procedure is defined in. - /// When , this procedure is a free function. - /// - public IClass? DeclaringType { get; } - - /// - /// The module this procedure is defined in. - /// - public IModule DeclaringModule { get; } - - /// - /// The assembly this procedure is defined in. - /// - public IAssembly Assembly { get; } - /// /// The entry basic block of this procedure. /// diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index a314f43ea..c0024a47d 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -30,27 +30,19 @@ internal sealed class Module : IModule public IReadOnlyDictionary Procedures => this.procedures; IReadOnlyDictionary IModule.Procedures => this.procedures; - public Assembly Assembly { get; } - IAssembly IModule.Assembly => this.Assembly; - - public Module? Parent { get; } - IModule? IModule.Parent => this.Parent; - private readonly HashSet fields = []; private readonly HashSet properties = []; private readonly Dictionary procedures = []; private readonly Dictionary submodules = []; private readonly Dictionary types = []; - public Module(ModuleSymbol symbol, Assembly assembly, Module? Parent) + public Module(ModuleSymbol symbol) { this.Symbol = symbol; this.GlobalInitializer = this.DefineProcedure(new IntrinsicFunctionSymbol( name: "", paramTypes: [], returnType: WellKnownTypes.Unit)); - this.Assembly = assembly; - this.Parent = Parent; } public ImmutableArray GetProcedures() @@ -71,7 +63,7 @@ public Procedure DefineProcedure(FunctionSymbol functionSymbol) { if (!this.procedures.TryGetValue(functionSymbol, out var result)) { - result = new Procedure(this, null, functionSymbol); + result = new Procedure(functionSymbol); this.procedures.Add(functionSymbol, result); } return (Procedure)result; @@ -81,7 +73,7 @@ public Module DefineModule(ModuleSymbol moduleSymbol) { if (!this.submodules.TryGetValue(moduleSymbol, out var result)) { - result = new Module(moduleSymbol, this.Assembly, this); + result = new Module(moduleSymbol); this.submodules.Add(moduleSymbol, result); } return (Module)result; @@ -91,7 +83,7 @@ public Class DefineType(TypeSymbol typeSymbol) { if (!this.types.TryGetValue(typeSymbol, out var result)) { - result = new Class(this, typeSymbol); + result = new Class(typeSymbol); this.types.Add(typeSymbol, result); } return (Class)result; diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index 3bd292fa4..abb23c9cd 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -14,12 +14,6 @@ internal sealed class Procedure : IProcedure { public FunctionSymbol Symbol { get; } public string Name => this.Symbol.NestedName; - public Module DeclaringModule { get; } - IModule IProcedure.DeclaringModule => this.DeclaringModule; - public Class? DeclaringType { get; } - IClass? IProcedure.DeclaringType => this.DeclaringType; - public Assembly Assembly => this.DeclaringModule.Assembly; - IAssembly IProcedure.Assembly => this.Assembly; public BasicBlock Entry { get; } IBasicBlock IProcedure.Entry => this.Entry; public IReadOnlyList Attributes => this.Symbol.Attributes; @@ -39,10 +33,8 @@ internal sealed class Procedure : IProcedure private readonly List locals = []; private readonly List registers = []; - public Procedure(Module declaringModule, Class? declaringType, FunctionSymbol symbol) + public Procedure(FunctionSymbol symbol) { - this.DeclaringModule = declaringModule; - this.DeclaringType = declaringType; this.Symbol = symbol; this.Entry = this.DefineBasicBlock(new SynthetizedLabelSymbol("begin")); } From 27f3e2fbfbadd2644f784222eedde5df56676ccd Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:32:43 +0100 Subject: [PATCH 086/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 0fb2fe6a5..e816e45ec 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -658,16 +658,9 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa var startFieldIndex = fieldIndex; var startProcIndex = procIndex; - var visibility = (@class.Symbol.Visibility, parent) switch - { - (Api.Semantics.Visibility.Public, not null) => TypeAttributes.NestedPublic, - (Api.Semantics.Visibility.Public, null) => TypeAttributes.Public, - (_, not null) => TypeAttributes.NestedAssembly, - (_, null) => TypeAttributes.NotPublic, - }; - - var attributes = visibility | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed; - + var visibility = GetClassVisibility(@class.Symbol.Visibility, parent is not null); + var attributes = visibility + | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed; if (@class.Symbol.IsValueType) attributes |= TypeAttributes.SequentialLayout; // AutoLayout = 0. var createdClass = this.AddTypeDefinition( @@ -910,6 +903,14 @@ private void WritePe(Stream peStream) peBlob.WriteContentTo(peStream); } + private static TypeAttributes GetClassVisibility(Api.Semantics.Visibility visibility, bool isNested) => (visibility, isNested) switch + { + (Api.Semantics.Visibility.Public, true) => TypeAttributes.NestedPublic, + (Api.Semantics.Visibility.Public, false) => TypeAttributes.Public, + (_, true) => TypeAttributes.NestedAssembly, + (_, false) => TypeAttributes.NotPublic, + }; + private static FieldAttributes GetFieldVisibility(Api.Semantics.Visibility visibility) => visibility switch { Api.Semantics.Visibility.Public => FieldAttributes.Public, From 21551630fb6e66bbf909db660a07796759217bf6 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:34:17 +0100 Subject: [PATCH 087/109] Update IClass.cs --- src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index f145cef73..524033c1e 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -4,7 +4,7 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; /// -/// Read-only interface if a +/// Interface of a class definition. /// internal interface IClass { From 3a8e6505639171a0b93ada59a8541d46c829a9e6 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:36:05 +0100 Subject: [PATCH 088/109] Update Module.cs --- .../Internal/OptimizingIr/Model/Module.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index c0024a47d..b7b18a76f 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -18,8 +18,8 @@ internal sealed class Module : IModule public IDictionary Submodules => this.submodules; IReadOnlyDictionary IModule.Submodules => this.submodules; - public IDictionary Types => this.types; - IReadOnlyDictionary IModule.Classes => this.types; + public IDictionary Classes => this.classes; + IReadOnlyDictionary IModule.Classes => this.classes; public IReadOnlySet Fields => this.fields; public IReadOnlySet Properties => this.properties; @@ -34,7 +34,7 @@ internal sealed class Module : IModule private readonly HashSet properties = []; private readonly Dictionary procedures = []; private readonly Dictionary submodules = []; - private readonly Dictionary types = []; + private readonly Dictionary classes = []; public Module(ModuleSymbol symbol) { @@ -81,10 +81,10 @@ public Module DefineModule(ModuleSymbol moduleSymbol) public Class DefineType(TypeSymbol typeSymbol) { - if (!this.types.TryGetValue(typeSymbol, out var result)) + if (!this.classes.TryGetValue(typeSymbol, out var result)) { result = new Class(typeSymbol); - this.types.Add(typeSymbol, result); + this.classes.Add(typeSymbol, result); } return (Class)result; } From b21515f8afdbf62a2aa01ac3396b58c8849426ba Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 7 Nov 2024 14:36:59 +0100 Subject: [PATCH 089/109] Rename --- .../Internal/OptimizingIr/Codegen/ModuleCodegen.cs | 2 +- src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs index 27eda9d64..86cbfd035 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ModuleCodegen.cs @@ -72,7 +72,7 @@ public override void VisitType(TypeSymbol typeSymbol) { if (typeSymbol is not SourceClassSymbol sourceClass) return; - var type = this.module.DefineType(typeSymbol); + var type = this.module.DefineClass(typeSymbol); var typeCodegen = new ClassCodegen(this, type); sourceClass.Accept(typeCodegen); } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs index b7b18a76f..3a46ef789 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Module.cs @@ -79,7 +79,7 @@ public Module DefineModule(ModuleSymbol moduleSymbol) return (Module)result; } - public Class DefineType(TypeSymbol typeSymbol) + public Class DefineClass(TypeSymbol typeSymbol) { if (!this.classes.TryGetValue(typeSymbol, out var result)) { From cca9b52b159c650bb1310079bc9ce4fcc1974b95 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 18:51:11 +0100 Subject: [PATCH 090/109] Reorder, rename --- .../Internal/Codegen/MetadataCodegen.cs | 2 +- .../Internal/OptimizingIr/Codegen/ClassCodegen.cs | 2 +- .../Internal/OptimizingIr/Model/Class.cs | 11 +++++------ .../Internal/OptimizingIr/Model/IClass.cs | 8 ++++---- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index e816e45ec..f79151ae8 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -673,7 +673,7 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa ); // Procedures - foreach (var proc in @class.Methods.Values) + foreach (var proc in @class.Procedures.Values) { if (proc.Symbol is DefaultConstructorSymbol ctor) { diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs index a3fc5bb9c..1170404d6 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -20,7 +20,7 @@ public override void VisitFunction(FunctionSymbol functionSymbol) if (functionSymbol.Body is null) return; // Add procedure - var procedure = @class.DefineMethod(functionSymbol); + var procedure = @class.DefineProcedure(functionSymbol); // Create the body var body = this.RewriteBody(functionSymbol.Body); diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs index be78a006d..869240aa8 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs @@ -8,25 +8,24 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; internal sealed class Class(TypeSymbol symbol) : IClass { - public TypeSymbol Symbol { get; } = symbol; public string Name => this.Symbol.Name; public IReadOnlyList Generics => this.Symbol.GenericParameters; - public IReadOnlyDictionary Methods => this.methods; + public IReadOnlyDictionary Procedures => this.procedures; public IReadOnlyList Fields => InterlockedUtils.InitializeDefault( ref this.fields, () => this.Symbol.DefinedMembers.OfType().ToImmutableArray()); private ImmutableArray fields; - private readonly Dictionary methods = []; + private readonly Dictionary procedures = []; - public Procedure DefineMethod(FunctionSymbol functionSymbol) + public Procedure DefineProcedure(FunctionSymbol functionSymbol) { - if (!this.methods.TryGetValue(functionSymbol, out var result)) + if (!this.procedures.TryGetValue(functionSymbol, out var result)) { result = new Procedure(functionSymbol); - this.methods.Add(functionSymbol, result); + this.procedures.Add(functionSymbol, result); } return (Procedure)result; } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index 524033c1e..32646ff36 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -24,12 +24,12 @@ internal interface IClass public IReadOnlyList Generics { get; } /// - /// The methods on this type. + /// The fields on this type. /// - public IReadOnlyDictionary Methods { get; } + public IReadOnlyList Fields { get; } /// - /// The fields on this type. + /// The procedures on this type. /// - public IReadOnlyList Fields { get; } + public IReadOnlyDictionary Procedures { get; } } From 38424970c0f9c9f4cbae8b5f91f63b18ad2ae2e8 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 18:55:34 +0100 Subject: [PATCH 091/109] Fixed errors --- .../Internal/Binding/Binder_Expression.cs | 2 +- .../Binding/SymbolResolutionErrors.cs | 25 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs index 638991f1f..ade60551c 100644 --- a/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs +++ b/src/Draco.Compiler/Internal/Binding/Binder_Expression.cs @@ -739,7 +739,7 @@ private BindingTask BindThisExpression(ThisExpressionSyntax syn { // No, report error diagnostics.Add(Diagnostic.Create( - template: SymbolResolutionErrors.NoThisInStaticMethod, + template: SymbolResolutionErrors.ThisReferencedInStaticMethod, location: syntax.Location, formatArgs: [this.ContainingSymbol!.Name])); diff --git a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs index fb75f1b21..25a0c57fc 100644 --- a/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs +++ b/src/Draco.Compiler/Internal/Binding/SymbolResolutionErrors.cs @@ -185,24 +185,24 @@ internal static class SymbolResolutionErrors format: "the {0} {1} is inaccessible due to its visibility", code: Code(19)); + /// + /// The this parameter is not first in the parameter list. + /// public static readonly DiagnosticTemplate ThisParameterNotFirst = DiagnosticTemplate.Create( title: "this parameter not first", severity: DiagnosticSeverity.Error, format: "the this parameter must be the first parameter", code: Code(20)); - public static readonly DiagnosticTemplate NoTypeInstanceToReference = DiagnosticTemplate.Create( - title: "no type instance to reference", + /// + /// This was referenced outside of a type. + /// + public static readonly DiagnosticTemplate ThisReferencedInStaticMethod = DiagnosticTemplate.Create( + title: "this reference in static method", severity: DiagnosticSeverity.Error, - format: "there is no type instance to reference.", + format: "this reference can not be referenced in the static method {0}", code: Code(21)); - public static readonly DiagnosticTemplate NoThisInStaticMethod = DiagnosticTemplate.Create( - title: "instance reference in static method", - severity: DiagnosticSeverity.Error, - format: "cannot reference the type instance in static method {0}", - code: Code(22)); - /// /// The return expression is illegal in the current context. /// @@ -210,11 +210,14 @@ internal static class SymbolResolutionErrors title: "illegal return", severity: DiagnosticSeverity.Error, format: "illegal return expression outside of function definition", - code: Code(23)); + code: Code(22)); + /// + /// The this expression is illegal in the current context. + /// public static readonly DiagnosticTemplate IllegalThis = DiagnosticTemplate.Create( title: "ilegal this", severity: DiagnosticSeverity.Error, format: "illegal this expression outside of a function definition", - code: Code(24)); + code: Code(23)); } From 05793a97de3a72d7bb02f0835eb25030469598d2 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 19:45:47 +0100 Subject: [PATCH 092/109] Update ParserTests.cs --- .../Syntax/ParserTests.cs | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs index f44cac6fc..4c13aa6fd 100644 --- a/src/Draco.Compiler.Tests/Syntax/ParserTests.cs +++ b/src/Draco.Compiler.Tests/Syntax/ParserTests.cs @@ -1915,39 +1915,6 @@ public void TestImportDeclarationWithVisibilityModifier() } } - [Fact] - public void TestClassDeclaration() - { - this.ParseDeclaration(""" - class Foo { - } - """); - - this.N(); - { - this.T(TokenKind.KeywordClass); - this.T(TokenKind.Identifier, "Foo"); - this.N(); - } - } - - [Fact] - public void TestValueClassDeclaration() - { - this.ParseDeclaration(""" - value class Foo { - } - """); - - this.N(); - { - this.T(TokenKind.KeywordValue); - this.T(TokenKind.KeywordClass); - this.T(TokenKind.Identifier, "Foo"); - this.N(); - } - } - [Fact] public void TestFunctionAndParameterWithAttribute() { @@ -2146,4 +2113,37 @@ func foo(x: List<>) {} } } } + + [Fact] + public void TestClassDeclaration() + { + this.ParseDeclaration(""" + class Foo { + } + """); + + this.N(); + { + this.T(TokenKind.KeywordClass); + this.T(TokenKind.Identifier, "Foo"); + this.N(); + } + } + + [Fact] + public void TestValueClassDeclaration() + { + this.ParseDeclaration(""" + value class Foo { + } + """); + + this.N(); + { + this.T(TokenKind.KeywordValue); + this.T(TokenKind.KeywordClass); + this.T(TokenKind.Identifier, "Foo"); + this.N(); + } + } } From f054f7b1b6b690a07dafe2f7c9330926a7427d95 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 19:47:22 +0100 Subject: [PATCH 093/109] Update CompilingCodeTests.cs --- src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs b/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs index 3a899204f..e55fdc014 100644 --- a/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs +++ b/src/Draco.Compiler.Tests/EndToEnd/CompilingCodeTests.cs @@ -1025,7 +1025,7 @@ public void InstanceField() var assembly = CompileToAssembly(""" import System.Console; - func main(): int32 { + func bar(): int32 { var foo = Foo(); foo.increment(); return foo.get(); @@ -1033,6 +1033,7 @@ func main(): int32 { class Foo { field var i: int32; + public func increment(this) { this.i += 1; } @@ -1043,8 +1044,7 @@ public func get(this): int32 { } """); - var stringWriter = new StringWriter(); - var value = Invoke(assembly: assembly, stdout: stringWriter); + var value = Invoke(assembly: assembly, methodName: "bar"); Assert.Equal(1, value); } } From 0d44315254dc8629345a065ed3fb6947b454178d Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 19:59:11 +0100 Subject: [PATCH 094/109] Update ConstructorFunctionSymbol.cs --- .../Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs index d3e28aff1..a1a8cb08b 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/ConstructorFunctionSymbol.cs @@ -19,6 +19,7 @@ internal sealed class ConstructorFunctionSymbol(FunctionSymbol ctorDefinition) : ctorDefinition.Visibility < this.ReturnType.Visibility ? ctorDefinition.Visibility : this.ReturnType.Visibility; public override SymbolDocumentation Documentation => ctorDefinition.Documentation; internal override string RawDocumentation => ctorDefinition.RawDocumentation; + public override Symbol? ContainingSymbol => ctorDefinition.ContainingSymbol; public override ImmutableArray GenericParameters => InterlockedUtils.InitializeDefault(ref this.genericParameters, this.BuildGenericParameters); From 50bc7fb827fa77a57662e5ce9abd8ef58d05033a Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 20:19:18 +0100 Subject: [PATCH 095/109] Made class props work --- .../AutoProperty/AutoPropertyGetterSymbol.cs | 16 +++++++++++++++- .../AutoProperty/AutoPropertySetterSymbol.cs | 16 +++++++++++++++- .../SynthetizedThisParameterSymbol.cs | 11 +++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertyGetterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertyGetterSymbol.cs index 9d7562c57..2fdf0bc10 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertyGetterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertyGetterSymbol.cs @@ -1,6 +1,7 @@ using Draco.Compiler.Internal.BoundTree; using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Symbols.Syntax; +using Draco.Compiler.Internal.Utilities; using System; using System.Collections.Immutable; using System.Threading; @@ -28,6 +29,12 @@ internal sealed class AutoPropertyGetterSymbol( public override BoundStatement Body => LazyInitializer.EnsureInitialized(ref this.body, this.BuildBody); private BoundStatement? body; + /// + /// An optional this parameter, if the getter is an instance method. + /// + public ParameterSymbol? ThisParameter => InterlockedUtils.InitializeMaybeNull(ref this.thisParameter, this.BuildThisParameter); + private ParameterSymbol? thisParameter; + PropertySymbol IPropertyAccessorSymbol.Property => this.Property; public SyntaxAutoPropertySymbol Property { get; } = property; @@ -36,7 +43,14 @@ private BoundStatement BuildBody() => ExpressionStatement(BlockExpression( statements: [ExpressionStatement(ReturnExpression(FieldExpression( receiver: this.IsStatic ? null - : throw new NotImplementedException("TODO: for classes"), + : ParameterExpression(this.ThisParameter!), field: this.Property.BackingField)))], value: BoundUnitExpression.Default)); + + private ParameterSymbol? BuildThisParameter() + { + if (this.IsStatic) return null; + + return new SynthetizedThisParameterSymbol(this); + } } diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertySetterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertySetterSymbol.cs index 763a18fc7..5f46de132 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertySetterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/AutoProperty/AutoPropertySetterSymbol.cs @@ -4,6 +4,7 @@ using Draco.Compiler.Internal.Utilities; using System; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Threading; using static Draco.Compiler.Internal.BoundTree.BoundTreeFactory; @@ -31,6 +32,12 @@ internal sealed class AutoPropertySetterSymbol( public override BoundStatement Body => LazyInitializer.EnsureInitialized(ref this.body, this.BuildBody); private BoundStatement? body; + /// + /// An optional this parameter, if the getter is an instance method. + /// + public ParameterSymbol? ThisParameter => InterlockedUtils.InitializeMaybeNull(ref this.thisParameter, this.BuildThisParameter); + private ParameterSymbol? thisParameter; + PropertySymbol IPropertyAccessorSymbol.Property => this.Property; public SyntaxAutoPropertySymbol Property { get; } = property; @@ -45,9 +52,16 @@ private BoundStatement BuildBody() => ExpressionStatement(BlockExpression( left: FieldLvalue( receiver: this.IsStatic ? null - : throw new NotImplementedException("TODO: classes"), + : ParameterExpression(this.ThisParameter!), field: this.Property.BackingField), right: ParameterExpression(this.Parameters[^1]))), ExpressionStatement(ReturnExpression(BoundUnitExpression.Default))], value: BoundUnitExpression.Default)); + + private ParameterSymbol? BuildThisParameter() + { + if (this.IsStatic) return null; + + return new SynthetizedThisParameterSymbol(this); + } } diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs new file mode 100644 index 000000000..05daaa0e2 --- /dev/null +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs @@ -0,0 +1,11 @@ +namespace Draco.Compiler.Internal.Symbols.Synthetized; + +/// +/// A compiler-generated this parameter. +/// +internal sealed class SynthetizedThisParameterSymbol(FunctionSymbol containingSymbol) : ParameterSymbol +{ + public override FunctionSymbol ContainingSymbol => containingSymbol; + public override TypeSymbol Type => (TypeSymbol)containingSymbol.ContainingSymbol!; + public override bool IsThis => true; +} From fc64a4db6aedf3c363f7e9f0949f26b12bda0a4a Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 20:33:58 +0100 Subject: [PATCH 096/109] Update SourceClassSymbol.cs --- .../Internal/Symbols/Source/SourceClassSymbol.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs index 39ba623e0..e54b0d94f 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceClassSymbol.cs @@ -88,6 +88,8 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) result.Add(new DefaultConstructorSymbol(this)); foreach (var member in blockBody.Declarations.Select(this.BuildMember)) { + if (member is null) continue; + var earlierMember = result.FirstOrDefault(s => s.Name == member.Name); result.Add(member); result.AddRange(member.GetAdditionalSymbols()); @@ -112,12 +114,13 @@ private ImmutableArray BindMembers(IBinderProvider binderProvider) return []; } - private Symbol BuildMember(DeclarationSyntax syntax) => syntax switch + private Symbol? BuildMember(DeclarationSyntax syntax) => syntax switch { FunctionDeclarationSyntax functionSyntax => new SourceFunctionSymbol(this, functionSyntax), VariableDeclarationSyntax varSyntax when varSyntax.FieldModifier is null => new SourceAutoPropertySymbol(this, varSyntax), VariableDeclarationSyntax varSyntax when varSyntax.FieldModifier is not null => new SourceFieldSymbol(this, varSyntax), - _ => throw new NotImplementedException(), // TODO implement this + UnexpectedDeclarationSyntax => null, + _ => throw new NotImplementedException(), }; public override string ToString() => $"{this.Name}{this.GenericsToString()}"; From 4a7df1a7e9a7ac206a47c999bc2b12e55b949017 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 20:46:51 +0100 Subject: [PATCH 097/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index f79151ae8..0df1ff1f9 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -191,6 +191,14 @@ public EntityHandle GetEntityHandle(Symbol symbol) return this.MetadataBuilder.AddTypeSpecification(blob); } + case SourceClassSymbol sourceClass: + { + return this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + } + case TypeSymbol typeSymbol: { var blob = this.EncodeBlob(e => @@ -663,27 +671,32 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed; if (@class.Symbol.IsValueType) attributes |= TypeAttributes.SequentialLayout; // AutoLayout = 0. - var createdClass = this.AddTypeDefinition( + var definitionHandle = this.AddTypeDefinition( attributes, null, @class.Name, @class.Symbol.IsValueType ? this.systemValueTypeReference : this.systemObjectReference, fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), - methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex) - ); + methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex)); + + // Add generic type parameters + var genericIndex = 0; + foreach (var typeParam in @class.Generics) + { + this.MetadataBuilder.AddGenericParameter( + parent: definitionHandle, + attributes: GenericParameterAttributes.None, + name: this.GetOrAddString(typeParam.Name), + index: genericIndex++); + } // Procedures foreach (var proc in @class.Procedures.Values) { - if (proc.Symbol is DefaultConstructorSymbol ctor) - { - var handle = this.EncodeProcedure(proc, ".ctor"); - } - else - { - var handle = this.EncodeProcedure(proc); - - } + var specialName = proc.Symbol is DefaultConstructorSymbol + ? ".ctor" + : null; + this.EncodeProcedure(proc, specialName: specialName); ++procIndex; // Todo: properties @@ -700,15 +713,15 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa if (@class.Symbol.IsValueType && @class.Fields.Count == 0) { this.MetadataBuilder.AddTypeLayout( - type: createdClass, + type: definitionHandle, packingSize: 0, size: 1); } // If this isn't top level module, we specify nested relationship - if (parent is not null) this.MetadataBuilder.AddNestedType(createdClass, parent.Value); + if (parent is not null) this.MetadataBuilder.AddNestedType(definitionHandle, parent.Value); - return createdClass; + return definitionHandle; } private IEnumerable ScalarConstantTypes => [ From 3d8db0c437129839b8654f7684917eefec235ed1 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 11 Nov 2024 21:07:20 +0100 Subject: [PATCH 098/109] Slight fixes --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 3 ++- src/Draco.Compiler/Internal/Symbols/Symbol.cs | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 0df1ff1f9..1d1c96f31 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -674,7 +674,8 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa var definitionHandle = this.AddTypeDefinition( attributes, null, - @class.Name, + // TODO: Maybe expose metadata name instead then instead of regular name? + @class.Symbol.MetadataName, @class.Symbol.IsValueType ? this.systemValueTypeReference : this.systemObjectReference, fieldList: MetadataTokens.FieldDefinitionHandle(startFieldIndex), methodList: MetadataTokens.MethodDefinitionHandle(startProcIndex)); diff --git a/src/Draco.Compiler/Internal/Symbols/Symbol.cs b/src/Draco.Compiler/Internal/Symbols/Symbol.cs index 0819db402..80af47243 100644 --- a/src/Draco.Compiler/Internal/Symbols/Symbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Symbol.cs @@ -88,7 +88,9 @@ public IEnumerable AncestorChain /// /// The metadata name of this symbol. /// - public virtual string MetadataName => this.Name; + public virtual string MetadataName => this.IsGenericDefinition + ? $"{this.Name}`{this.GenericParameters.Length}" + : this.Name; /// /// The name of this symbol. From f0526b62855a46e32bf36959850fd63e370a1e83 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Tue, 12 Nov 2024 08:58:22 +0100 Subject: [PATCH 099/109] Fix --- src/Draco.Compiler/Internal/Codegen/CilCodegen.cs | 7 ++++++- .../Internal/OptimizingIr/Model/Procedure.cs | 7 ++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs index 3ae539d86..a4d0acb2b 100644 --- a/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/CilCodegen.cs @@ -72,7 +72,12 @@ public CilCodegen(MetadataCodegen metadataCodegen, IProcedure procedure) private EntityHandle GetHandle(Symbol symbol) => this.metadataCodegen.GetEntityHandle(symbol); // TODO: Parameters don't handle unit yet, it introduces some signature problems - private int GetParameterIndex(ParameterSymbol parameter) => this.procedure.GetParameterIndex(parameter); + private int GetParameterIndex(ParameterSymbol parameter) + { + if (parameter.IsThis) return 0; + return this.procedure.GetParameterIndex(parameter) + + (parameter.ContainingSymbol.IsStatic ? 0 : 1); + } private AllocatedLocal? GetAllocatedLocal(LocalSymbol local) { diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index abb23c9cd..a610d293d 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -41,10 +42,10 @@ public Procedure(FunctionSymbol symbol) public int GetParameterIndex(ParameterSymbol symbol) { - if (symbol.IsThis) return 0; + if (symbol.IsThis) throw new ArgumentOutOfRangeException(nameof(symbol), "this parameter is treated special"); var idx = this.Symbol.Parameters.IndexOf(symbol); - if (idx == -1) throw new System.ArgumentOutOfRangeException(nameof(symbol)); - return symbol.ContainingSymbol.IsStatic ? idx : idx + 1; + if (idx == -1) throw new ArgumentOutOfRangeException(nameof(symbol)); + return idx; } public BasicBlock DefineBasicBlock(LabelSymbol symbol) From d418c40e38bd9b20ab33566290c9c39050b30814 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Tue, 12 Nov 2024 09:12:51 +0100 Subject: [PATCH 100/109] Codegen and IR fix --- .../Internal/Codegen/MetadataCodegen.cs | 30 ++++++++++++++++--- .../OptimizingIr/Codegen/ClassCodegen.cs | 18 ++++++++++- .../Internal/OptimizingIr/Model/Class.cs | 12 +++++--- .../Internal/OptimizingIr/Model/IClass.cs | 18 +++++++---- 4 files changed, 63 insertions(+), 15 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 1d1c96f31..ce8c39862 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -526,11 +526,12 @@ private void EncodeModule(IModule module, TypeDefinitionHandle? parent, ref int private FieldDefinitionHandle EncodeField(FieldSymbol field) { - var visibility = GetFieldVisibility(field.Visibility); + var attributes = GetFieldVisibility(field.Visibility); + if (field.IsStatic) attributes |= FieldAttributes.Static; // Definition return this.AddFieldDefinition( - attributes: visibility | FieldAttributes.Static, + attributes: attributes, name: field.Name, signature: this.EncodeFieldSignature(field)); } @@ -691,16 +692,37 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa index: genericIndex++); } + // Properties + // TODO: Copypasta + var firstProperty = null as PropertyDefinitionHandle?; + var propertyHandleMap = new Dictionary(); + foreach (var prop in @class.Properties) + { + var propHandle = this.EncodeProperty(definitionHandle, prop); + firstProperty ??= propHandle; + propertyHandleMap.Add(prop, propHandle); + } + if (firstProperty is not null) this.MetadataBuilder.AddPropertyMap(definitionHandle, firstProperty.Value); + // Procedures foreach (var proc in @class.Procedures.Values) { var specialName = proc.Symbol is DefaultConstructorSymbol ? ".ctor" : null; - this.EncodeProcedure(proc, specialName: specialName); + var handle = this.EncodeProcedure(proc, specialName: specialName); ++procIndex; - // Todo: properties + // TODO: Copypasta + if (proc.Symbol is IPropertyAccessorSymbol propAccessor) + { + // This is an accessor + var isGetter = propAccessor.Property.Getter == propAccessor; + this.MetadataBuilder.AddMethodSemantics( + association: propertyHandleMap[propAccessor.Property], + semantics: isGetter ? MethodSemanticsAttributes.Getter : MethodSemanticsAttributes.Setter, + methodDefinition: handle); + } } // Fields diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs index 1170404d6..bcc68f7b9 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Codegen/ClassCodegen.cs @@ -3,6 +3,9 @@ using Draco.Compiler.Internal.Lowering; using Draco.Compiler.Internal.OptimizingIr.Model; using Draco.Compiler.Internal.Symbols; +using Draco.Compiler.Internal.Symbols.Source; +using Draco.Compiler.Internal.Symbols.Syntax; +using Draco.Compiler.Internal.Symbols.Synthetized.AutoProperty; namespace Draco.Compiler.Internal.OptimizingIr.Codegen; @@ -36,7 +39,20 @@ public override void VisitFunction(FunctionSymbol functionSymbol) public override void VisitField(FieldSymbol fieldSymbol) { - // No-op, the Class model reads it up from the symbol + if (fieldSymbol is not SyntaxFieldSymbol and not AutoPropertyBackingFieldSymbol) return; + + // TODO: Initializer value + @class.DefineField(fieldSymbol); + } + + public override void VisitProperty(PropertySymbol propertySymbol) + { + // TODO: Not flexible, won't work for non-auto props + if (propertySymbol is not SyntaxAutoPropertySymbol) return; + + @class.DefineProperty(propertySymbol); + + // TODO: Initializer value } private BoundNode RewriteBody(BoundNode body) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs index 869240aa8..5b29ff8ec 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Class.cs @@ -13,13 +13,17 @@ internal sealed class Class(TypeSymbol symbol) : IClass public IReadOnlyList Generics => this.Symbol.GenericParameters; public IReadOnlyDictionary Procedures => this.procedures; - public IReadOnlyList Fields => InterlockedUtils.InitializeDefault( - ref this.fields, - () => this.Symbol.DefinedMembers.OfType().ToImmutableArray()); - private ImmutableArray fields; + public IReadOnlySet Fields => this.fields; + public IReadOnlySet Properties => this.properties; + + private readonly HashSet fields = []; + private readonly HashSet properties = []; private readonly Dictionary procedures = []; + public void DefineField(FieldSymbol fieldSymbol) => this.fields.Add(fieldSymbol); + public void DefineProperty(PropertySymbol propertySymbol) => this.properties.Add(propertySymbol); + public Procedure DefineProcedure(FunctionSymbol functionSymbol) { if (!this.procedures.TryGetValue(functionSymbol, out var result)) diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs index 32646ff36..9eefc08f5 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/IClass.cs @@ -9,27 +9,33 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; internal interface IClass { /// - /// The symbol of this type. + /// The symbol of this class. /// public TypeSymbol Symbol { get; } /// - /// The name of this type. + /// The name of this class. /// public string Name { get; } /// - /// The generic parameters on this type. + /// The generic parameters on this class. /// public IReadOnlyList Generics { get; } + // TODO: Fields and props should be order-dependent for classes and modules too /// - /// The fields on this type. + /// The fields on this class. /// - public IReadOnlyList Fields { get; } + public IReadOnlySet Fields { get; } /// - /// The procedures on this type. + /// The properties within this class. + /// + public IReadOnlySet Properties { get; } + + /// + /// The procedures on this class. /// public IReadOnlyDictionary Procedures { get; } } From 02ed12352b806e4b77d3406145bc06d2b3460627 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 13 Nov 2024 10:56:54 +0100 Subject: [PATCH 101/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index ce8c39862..d25f66ae5 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -305,6 +305,35 @@ Symbol GetContainingSymbol() case FieldSymbol field: { + // TODO: Hack, is there some more general way to deal with this? + // Problem is that we need to generic instantiate the parent of the field reference... + // Otherwise the field ref will look Package::Type::field instead of Package::Type::field + if (field.ContainingSymbol is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + var parentGeneric = this.GetEntityHandle(sourceClass); + var parentInstance = this.EncodeBlob(e => + { + var argsEncoder = e + .TypeSpecificationSignature() + .GenericInstantiation( + genericType: parentGeneric, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + }); + return this.AddMemberReference( + parent: this.MetadataBuilder.AddTypeSpecification(parentInstance), + name: field.Name, + signature: this.EncodeBlob(e => + { + var encoder = e.Field(); + this.EncodeSignatureType(encoder.Type(), field.Type); + })); + } + return this.AddMemberReference( parent: this.GetEntityHandle(field.ContainingSymbol ?? throw new InvalidOperationException()), From 3429e63d273b30688ec9d1347c2f70c82b08aa71 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 13 Nov 2024 15:40:08 +0100 Subject: [PATCH 102/109] Update MetadataCodegen.cs --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index d25f66ae5..0709d8b17 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -240,6 +240,16 @@ Symbol GetContainingSymbol() } if (func.ContainingSymbol is not TypeSymbol type) return func.ContainingSymbol!; + + if (type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + // TODO: Same hack as for FieldSymbol + var generics = sourceClass.GenericParameters + .Cast() + .ToImmutableArray(); + return sourceClass.GenericInstantiate(sourceClass.ContainingSymbol, generics); + } + if (!type.IsArrayType) return type; // NOTE: This hack is present because of Arrays spit out stuff from their base types // to take priority From a42b49f87a2e0a4e86b9ccfaecfeb1417f6c10e0 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 13 Nov 2024 15:53:44 +0100 Subject: [PATCH 103/109] Update MetadataCodegen.cs --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 0709d8b17..f326d1777 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -232,6 +232,7 @@ Symbol GetContainingSymbol() { if (func.IsNested) { + // TODO: This can be fixed by moving this structural responsibility to the IR // We can't have nested functions represented in metadata directly, so we'll climb up the parent chain // To find the first non-function container return func.AncestorChain From 4e71a87e36d642a1864ae1bdb662abd6726bec14 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Wed, 13 Nov 2024 16:08:39 +0100 Subject: [PATCH 104/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 60 +++++++------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index f326d1777..c1548482d 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -17,6 +17,7 @@ using Draco.Compiler.Internal.Symbols.Source; using Draco.Compiler.Internal.Symbols.Synthetized; using Draco.Compiler.Internal.Symbols.Synthetized.Array; +using static System.Reflection.Metadata.BlobBuilder; namespace Draco.Compiler.Internal.Codegen; @@ -178,6 +179,7 @@ public EntityHandle GetEntityHandle(Symbol symbol) var blob = this.EncodeBlob(e => { var encoder = e.TypeSpecificationSignature(); + // TODO: Fix this callsite for source classes var typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); var argsEncoder = encoder.GenericInstantiation( genericType: typeRef, @@ -191,12 +193,28 @@ public EntityHandle GetEntityHandle(Symbol symbol) return this.MetadataBuilder.AddTypeSpecification(blob); } - case SourceClassSymbol sourceClass: + case SourceClassSymbol sourceClass when sourceClass.IsGenericDefinition: { - return this.GetOrAddTypeReference( + // TODO: Hack... Needed for fields for example, as... + // Problem is that we need to generic instantiate the parent of the field reference... + // Otherwise the field ref will look Package::Type::field instead of Package::Type::field + // TODO: This is also horribly incorrect + var genericHandle = this.GetOrAddTypeReference( parent: this.GetEntityHandle(sourceClass.ContainingSymbol), @namespace: null, name: sourceClass.MetadataName); + var genericInstance = this.EncodeBlob(e => + { + var argsEncoder = e.TypeSpecificationSignature().GenericInstantiation( + genericType: genericHandle, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + }); + return this.MetadataBuilder.AddTypeSpecification(genericInstance); } case TypeSymbol typeSymbol: @@ -242,15 +260,6 @@ Symbol GetContainingSymbol() if (func.ContainingSymbol is not TypeSymbol type) return func.ContainingSymbol!; - if (type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) - { - // TODO: Same hack as for FieldSymbol - var generics = sourceClass.GenericParameters - .Cast() - .ToImmutableArray(); - return sourceClass.GenericInstantiate(sourceClass.ContainingSymbol, generics); - } - if (!type.IsArrayType) return type; // NOTE: This hack is present because of Arrays spit out stuff from their base types // to take priority @@ -316,35 +325,6 @@ Symbol GetContainingSymbol() case FieldSymbol field: { - // TODO: Hack, is there some more general way to deal with this? - // Problem is that we need to generic instantiate the parent of the field reference... - // Otherwise the field ref will look Package::Type::field instead of Package::Type::field - if (field.ContainingSymbol is SourceClassSymbol { IsGenericDefinition: true } sourceClass) - { - var parentGeneric = this.GetEntityHandle(sourceClass); - var parentInstance = this.EncodeBlob(e => - { - var argsEncoder = e - .TypeSpecificationSignature() - .GenericInstantiation( - genericType: parentGeneric, - genericArgumentCount: sourceClass.GenericParameters.Length, - isValueType: sourceClass.IsValueType); - foreach (var param in sourceClass.GenericParameters) - { - this.EncodeSignatureType(argsEncoder.AddArgument(), param); - } - }); - return this.AddMemberReference( - parent: this.MetadataBuilder.AddTypeSpecification(parentInstance), - name: field.Name, - signature: this.EncodeBlob(e => - { - var encoder = e.Field(); - this.EncodeSignatureType(encoder.Type(), field.Type); - })); - } - return this.AddMemberReference( parent: this.GetEntityHandle(field.ContainingSymbol ?? throw new InvalidOperationException()), From a6a5d9e85c0fb4d9a4b45d9e66143e31a4f78db4 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Thu, 14 Nov 2024 13:04:28 +0100 Subject: [PATCH 105/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 78 +++++++++++++++++-- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index c1548482d..f68012868 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -179,8 +179,21 @@ public EntityHandle GetEntityHandle(Symbol symbol) var blob = this.EncodeBlob(e => { var encoder = e.TypeSpecificationSignature(); - // TODO: Fix this callsite for source classes - var typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); + EntityHandle typeRef; + // TODO: Hack for source-class generics + if (typeSymbol.GenericDefinition is SourceClassSymbol sourceClass) + { + // TODO: Copypasta + // TODO: This is also horribly incorrect + typeRef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + } + else + { + typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); + } var argsEncoder = encoder.GenericInstantiation( genericType: typeRef, genericArgumentCount: typeSymbol.GenericArguments.Length, @@ -809,12 +822,52 @@ private StandaloneSignatureHandle EncodeLocals( foreach (var local in locals) { var typeEncoder = localsEncoder.AddVariable().Type(); - this.EncodeSignatureType(typeEncoder, local.Symbol.Type); + if (local.Symbol.Type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + // TODO: That _DAMN_ ugly hack again... + // Copypasta... + var genericDef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + var argsEncoder = typeEncoder.GenericInstantiation( + genericType: genericDef, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + } + else + { + this.EncodeSignatureType(typeEncoder, local.Symbol.Type); + } } foreach (var register in registers) { var typeEncoder = localsEncoder.AddVariable().Type(); - this.EncodeSignatureType(typeEncoder, register.Type); + if (register.Type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + // TODO: That _DAMN_ ugly hack again... + // Copypasta... + var genericDef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass.ContainingSymbol), + @namespace: null, + name: sourceClass.MetadataName); + var argsEncoder = typeEncoder.GenericInstantiation( + genericType: genericDef, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + } + else + { + this.EncodeSignatureType(typeEncoder, register.Type); + } } })); } @@ -882,8 +935,23 @@ public void EncodeSignatureType(SignatureTypeEncoder encoder, TypeSymbol type) // Generic instantiation Debug.Assert(type.GenericDefinition is not null); + // TODO: That ugly hack again... + EntityHandle typeRef; + if (type.GenericDefinition is SourceClassSymbol sourceClass2) + { + // TODO: Copypasta + // TODO: This is also horribly incorrect + typeRef = this.GetOrAddTypeReference( + parent: this.GetEntityHandle(sourceClass2.ContainingSymbol), + @namespace: null, + name: sourceClass2.MetadataName); + } + else + { + typeRef = this.GetEntityHandle(type.GenericDefinition); + } var genericsEncoder = encoder.GenericInstantiation( - genericType: this.GetEntityHandle(type.GenericDefinition), + genericType: typeRef, genericArgumentCount: type.GenericArguments.Length, isValueType: type.IsValueType); foreach (var arg in type.GenericArguments) From 1b79b58af804a493c9c5c40e4af896317147c52d Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 18 Nov 2024 21:18:59 +0100 Subject: [PATCH 106/109] Simplification --- .../Internal/Codegen/MetadataCodegen.cs | 97 ++----------------- .../Source/SourceThisParameterSymbol.cs | 18 +++- .../SynthetizedThisParameterSymbol.cs | 21 +++- 3 files changed, 43 insertions(+), 93 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index f68012868..e013bcb26 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -179,21 +179,7 @@ public EntityHandle GetEntityHandle(Symbol symbol) var blob = this.EncodeBlob(e => { var encoder = e.TypeSpecificationSignature(); - EntityHandle typeRef; - // TODO: Hack for source-class generics - if (typeSymbol.GenericDefinition is SourceClassSymbol sourceClass) - { - // TODO: Copypasta - // TODO: This is also horribly incorrect - typeRef = this.GetOrAddTypeReference( - parent: this.GetEntityHandle(sourceClass.ContainingSymbol), - @namespace: null, - name: sourceClass.MetadataName); - } - else - { - typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); - } + var typeRef = this.GetEntityHandle(typeSymbol.GenericDefinition); var argsEncoder = encoder.GenericInstantiation( genericType: typeRef, genericArgumentCount: typeSymbol.GenericArguments.Length, @@ -206,28 +192,13 @@ public EntityHandle GetEntityHandle(Symbol symbol) return this.MetadataBuilder.AddTypeSpecification(blob); } - case SourceClassSymbol sourceClass when sourceClass.IsGenericDefinition: + case SourceClassSymbol sourceClass: { - // TODO: Hack... Needed for fields for example, as... - // Problem is that we need to generic instantiate the parent of the field reference... - // Otherwise the field ref will look Package::Type::field instead of Package::Type::field - // TODO: This is also horribly incorrect - var genericHandle = this.GetOrAddTypeReference( + // TODO: Possibly very incorrect + return this.GetOrAddTypeReference( parent: this.GetEntityHandle(sourceClass.ContainingSymbol), @namespace: null, name: sourceClass.MetadataName); - var genericInstance = this.EncodeBlob(e => - { - var argsEncoder = e.TypeSpecificationSignature().GenericInstantiation( - genericType: genericHandle, - genericArgumentCount: sourceClass.GenericParameters.Length, - isValueType: sourceClass.IsValueType); - foreach (var param in sourceClass.GenericParameters) - { - this.EncodeSignatureType(argsEncoder.AddArgument(), param); - } - }); - return this.MetadataBuilder.AddTypeSpecification(genericInstance); } case TypeSymbol typeSymbol: @@ -822,52 +793,12 @@ private StandaloneSignatureHandle EncodeLocals( foreach (var local in locals) { var typeEncoder = localsEncoder.AddVariable().Type(); - if (local.Symbol.Type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) - { - // TODO: That _DAMN_ ugly hack again... - // Copypasta... - var genericDef = this.GetOrAddTypeReference( - parent: this.GetEntityHandle(sourceClass.ContainingSymbol), - @namespace: null, - name: sourceClass.MetadataName); - var argsEncoder = typeEncoder.GenericInstantiation( - genericType: genericDef, - genericArgumentCount: sourceClass.GenericParameters.Length, - isValueType: sourceClass.IsValueType); - foreach (var param in sourceClass.GenericParameters) - { - this.EncodeSignatureType(argsEncoder.AddArgument(), param); - } - } - else - { - this.EncodeSignatureType(typeEncoder, local.Symbol.Type); - } + this.EncodeSignatureType(typeEncoder, local.Symbol.Type); } foreach (var register in registers) { var typeEncoder = localsEncoder.AddVariable().Type(); - if (register.Type is SourceClassSymbol { IsGenericDefinition: true } sourceClass) - { - // TODO: That _DAMN_ ugly hack again... - // Copypasta... - var genericDef = this.GetOrAddTypeReference( - parent: this.GetEntityHandle(sourceClass.ContainingSymbol), - @namespace: null, - name: sourceClass.MetadataName); - var argsEncoder = typeEncoder.GenericInstantiation( - genericType: genericDef, - genericArgumentCount: sourceClass.GenericParameters.Length, - isValueType: sourceClass.IsValueType); - foreach (var param in sourceClass.GenericParameters) - { - this.EncodeSignatureType(argsEncoder.AddArgument(), param); - } - } - else - { - this.EncodeSignatureType(typeEncoder, register.Type); - } + this.EncodeSignatureType(typeEncoder, register.Type); } })); } @@ -935,21 +866,7 @@ public void EncodeSignatureType(SignatureTypeEncoder encoder, TypeSymbol type) // Generic instantiation Debug.Assert(type.GenericDefinition is not null); - // TODO: That ugly hack again... - EntityHandle typeRef; - if (type.GenericDefinition is SourceClassSymbol sourceClass2) - { - // TODO: Copypasta - // TODO: This is also horribly incorrect - typeRef = this.GetOrAddTypeReference( - parent: this.GetEntityHandle(sourceClass2.ContainingSymbol), - @namespace: null, - name: sourceClass2.MetadataName); - } - else - { - typeRef = this.GetEntityHandle(type.GenericDefinition); - } + var typeRef = this.GetEntityHandle(type.GenericDefinition); var genericsEncoder = encoder.GenericInstantiation( genericType: typeRef, genericArgumentCount: type.GenericArguments.Length, diff --git a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs index 24797b47b..ed678bfa1 100644 --- a/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Source/SourceThisParameterSymbol.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Immutable; using System.Linq; +using System.Threading; using Draco.Compiler.Api.Syntax; using Draco.Compiler.Internal.Binding; @@ -18,7 +19,9 @@ internal sealed class SourceThisParameterSymbol : ParameterSymbol, ISourceSymbol public override ThisParameterSyntax DeclaringSyntax { get; } public override ImmutableArray Attributes => []; - public override TypeSymbol Type { get; } + + public override TypeSymbol Type => LazyInitializer.EnsureInitialized(ref this.type, this.BuildType); + private TypeSymbol? type; public SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterSyntax syntax) { @@ -29,8 +32,19 @@ public SourceThisParameterSymbol(FunctionSymbol containingSymbol, ThisParameterS this.ContainingSymbol = containingSymbol; this.DeclaringSyntax = syntax; - this.Type = containingType; } public void Bind(IBinderProvider binderProvider) { } + + private TypeSymbol BuildType() + { + var containingType = this.ContainingSymbol.AncestorChain + .OfType() + .First(); + + if (!containingType.IsGenericDefinition) return containingType; + + var genericArgs = containingType.GenericParameters.Cast().ToImmutableArray(); + return containingType.GenericInstantiate(containingType.ContainingSymbol, genericArgs); + } } diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs index 05daaa0e2..88a1537c4 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedThisParameterSymbol.cs @@ -1,3 +1,8 @@ +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using Draco.Compiler.Internal.Utilities; + namespace Draco.Compiler.Internal.Symbols.Synthetized; /// @@ -6,6 +11,20 @@ namespace Draco.Compiler.Internal.Symbols.Synthetized; internal sealed class SynthetizedThisParameterSymbol(FunctionSymbol containingSymbol) : ParameterSymbol { public override FunctionSymbol ContainingSymbol => containingSymbol; - public override TypeSymbol Type => (TypeSymbol)containingSymbol.ContainingSymbol!; public override bool IsThis => true; + + public override TypeSymbol Type => LazyInitializer.EnsureInitialized(ref this.type, this.BuildType); + private TypeSymbol? type; + + private TypeSymbol BuildType() + { + var containingType = this.ContainingSymbol.AncestorChain + .OfType() + .First(); + + if (!containingType.IsGenericDefinition) return containingType; + + var genericArgs = containingType.GenericParameters.Cast().ToImmutableArray(); + return containingType.GenericInstantiate(containingType.ContainingSymbol, genericArgs); + } } From bf23220b1a1302a5235419dfb2d74b354f06e0f2 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Mon, 18 Nov 2024 21:36:56 +0100 Subject: [PATCH 107/109] Update MetadataCodegen.cs --- .../Internal/Codegen/MetadataCodegen.cs | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index e013bcb26..0491ce61d 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -309,9 +309,25 @@ Symbol GetContainingSymbol() case FieldSymbol field: { + var parentHandle = this.GetEntityHandle(field.ContainingSymbol ?? throw new InvalidOperationException()); + // NOTE: Hack for field definitions for generics + if (field.ContainingSymbol is SourceClassSymbol { IsGenericDefinition: true } sourceClass) + { + var genericInstance = this.EncodeBlob(e => + { + var argsEncoder = e.TypeSpecificationSignature().GenericInstantiation( + genericType: parentHandle, + genericArgumentCount: sourceClass.GenericParameters.Length, + isValueType: sourceClass.IsValueType); + foreach (var param in sourceClass.GenericParameters) + { + this.EncodeSignatureType(argsEncoder.AddArgument(), param); + } + }); + parentHandle = this.MetadataBuilder.AddTypeSpecification(genericInstance); + } return this.AddMemberReference( - parent: this.GetEntityHandle(field.ContainingSymbol - ?? throw new InvalidOperationException()), + parent: parentHandle, name: field.Name, signature: this.EncodeBlob(e => { From 670c6d455322dc366dcfaac7efc150732b9c0fc7 Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Tue, 19 Nov 2024 22:21:21 +0100 Subject: [PATCH 108/109] Naming fixes --- src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs | 3 ++- src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs | 4 ++++ .../Internal/Symbols/Synthetized/SynthetizedAliasSymbol.cs | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 0491ce61d..4d1130a94 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -603,7 +603,8 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure, string? spe var definitionHandle = this.MetadataBuilder.AddMethodDefinition( attributes: attributes, implAttributes: MethodImplAttributes.IL, - name: this.GetOrAddString(specialName ?? procedure.Name), + // TODO: Maybe expose metadata name directly? + name: this.GetOrAddString(specialName ?? procedure.Symbol.MetadataName), signature: this.EncodeProcedureSignature(procedure), bodyOffset: methodBodyOffset, parameterList: parameterList); diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index c8598c0a7..37e9ddc22 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -110,6 +110,10 @@ public delegate IOperand CodegenDelegate( public override bool IsSpecialName => this.IsConstructor; + // NOTE: It seems like the backtick is only for types + // TODO: In that case, maybe move this logic out from Symbol and make MetadataName abstract or default to this instead? + public override string MetadataName => this.Name; + // NOTE: We override for covariant return type public override FunctionSymbol? GenericDefinition => null; public override IEnumerable Members => this.Parameters; diff --git a/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedAliasSymbol.cs b/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedAliasSymbol.cs index 85145ea63..dbf78607c 100644 --- a/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedAliasSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/Synthetized/SynthetizedAliasSymbol.cs @@ -5,7 +5,8 @@ namespace Draco.Compiler.Internal.Symbols.Synthetized; /// internal sealed class SynthetizedAliasSymbol(string name, Symbol substitution) : AliasSymbol { - public override string Name { get; } = name; + public override string MetadataName => this.Substitution.MetadataName; + public override string Name => name; public override Symbol Substitution { get; } = substitution; public override Api.Semantics.Visibility Visibility => Api.Semantics.Visibility.Public; } From 0bbfb53616131edfe118117b0ef0a7bbfbdca23d Mon Sep 17 00:00:00 2001 From: LPeter1997 Date: Tue, 19 Nov 2024 22:30:43 +0100 Subject: [PATCH 109/109] Tests pass --- .../Internal/Codegen/MetadataCodegen.cs | 20 +++++++++---------- .../Internal/OptimizingIr/Model/Procedure.cs | 2 +- .../Internal/Symbols/FunctionSymbol.cs | 13 ++++-------- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs index 4d1130a94..d7102d6c4 100644 --- a/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs +++ b/src/Draco.Compiler/Internal/Codegen/MetadataCodegen.cs @@ -265,7 +265,7 @@ Symbol GetContainingSymbol() parent: func.ContainingSymbol is null ? (EntityHandle)this.ModuleDefinitionHandle : this.GetEntityHandle(GetContainingSymbol()), - name: func.NestedName, + name: func.MetadataName, signature: this.EncodeBlob(e => { // In generic instances we still need to reference the generic types @@ -298,9 +298,9 @@ Symbol GetContainingSymbol() ? (EntityHandle)this.ModuleDefinitionHandle // We take its parent module : this.GetEntityHandle(parent); - var name = string.IsNullOrEmpty(moduleSymbol.Name) + var name = string.IsNullOrEmpty(moduleSymbol.MetadataName) ? CompilerConstants.DefaultModuleName - : moduleSymbol.Name; + : moduleSymbol.MetadataName; return this.GetOrAddTypeReference( parent: resolutionScope, @namespace: null, @@ -328,7 +328,7 @@ Symbol GetContainingSymbol() } return this.AddMemberReference( parent: parentHandle, - name: field.Name, + name: field.MetadataName, signature: this.EncodeBlob(e => { var encoder = e.Field(); @@ -410,7 +410,7 @@ private EntityHandle GetMultidimensionalArrayTypeHandle(TypeSymbol elementType, private AssemblyReferenceHandle AddAssemblyReference(MetadataAssemblySymbol module) => this.GetOrAddAssemblyReference( - name: module.Name, + name: module.MetadataName, version: module.Version); private static string? GetNamespaceForSymbol(Symbol? symbol) => symbol switch @@ -552,7 +552,7 @@ private FieldDefinitionHandle EncodeField(FieldSymbol field) // Definition return this.AddFieldDefinition( attributes: attributes, - name: field.Name, + name: field.MetadataName, signature: this.EncodeFieldSignature(field)); } @@ -592,7 +592,7 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure, string? spe { var paramHandle = this.AddParameterDefinition( attributes: ParameterAttributes.None, - name: param.Name, + name: param.MetadataName, index: procedure.GetParameterIndex(param)); // Add attributes @@ -619,7 +619,7 @@ private MethodDefinitionHandle EncodeProcedure(IProcedure procedure, string? spe this.MetadataBuilder.AddGenericParameter( parent: definitionHandle, attributes: GenericParameterAttributes.None, - name: this.GetOrAddString(typeParam.Name), + name: this.GetOrAddString(typeParam.MetadataName), index: genericIndex++); } @@ -633,7 +633,7 @@ private PropertyDefinitionHandle EncodeProperty( TypeDefinitionHandle declaringType, PropertySymbol prop) => this.MetadataBuilder.AddProperty( attributes: PropertyAttributes.None, - name: this.GetOrAddString(prop.Name), + name: this.GetOrAddString(prop.MetadataName), signature: this.EncodeBlob(e => { e @@ -709,7 +709,7 @@ private TypeDefinitionHandle EncodeClass(IClass @class, TypeDefinitionHandle? pa this.MetadataBuilder.AddGenericParameter( parent: definitionHandle, attributes: GenericParameterAttributes.None, - name: this.GetOrAddString(typeParam.Name), + name: this.GetOrAddString(typeParam.MetadataName), index: genericIndex++); } diff --git a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs index a610d293d..6366b0d89 100644 --- a/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs +++ b/src/Draco.Compiler/Internal/OptimizingIr/Model/Procedure.cs @@ -14,7 +14,7 @@ namespace Draco.Compiler.Internal.OptimizingIr.Model; internal sealed class Procedure : IProcedure { public FunctionSymbol Symbol { get; } - public string Name => this.Symbol.NestedName; + public string Name => this.Symbol.Name; public BasicBlock Entry { get; } IBasicBlock IProcedure.Entry => this.Entry; public IReadOnlyList Attributes => this.Symbol.Attributes; diff --git a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs index 37e9ddc22..d572ad244 100644 --- a/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs +++ b/src/Draco.Compiler/Internal/Symbols/FunctionSymbol.cs @@ -110,6 +110,10 @@ public delegate IOperand CodegenDelegate( public override bool IsSpecialName => this.IsConstructor; + // TODO: Apart from exposing the metadata name here, we need to take care of nested names for local methods for example + // The name should include the parent functions too, like func foo() { func bar() { ... } } + // the inner method should be called foo.bar in metadata + // NOTE: It seems like the backtick is only for types // TODO: In that case, maybe move this logic out from Symbol and make MetadataName abstract or default to this instead? public override string MetadataName => this.Name; @@ -137,15 +141,6 @@ public delegate IOperand CodegenDelegate( /// public virtual CodegenDelegate? Codegen => null; - /// - /// Retrieves the nested name of this function, which prepends the containing function names. - /// - public string NestedName => this.ContainingSymbol switch - { - FunctionSymbol f => $"{f.NestedName}.{this.Name}", - _ => this.Name, - }; - public override string ToString() { var result = new StringBuilder();