From 329317a412f0e4516ea60ba9852d6739374597d2 Mon Sep 17 00:00:00 2001 From: Chris Anders Date: Mon, 2 Dec 2024 08:15:25 +0100 Subject: [PATCH] refactor: Cleanup --- .../Backlang.Build.Tasks/Backlang.Sdk.csproj | 49 +++ NewSource/Backlang.Build.Tasks/BuildTask.cs | 59 +++ .../Core/Backlang.Core.props | 9 + .../Core/Backlang.Core.targets | 19 + .../Core/Backlang.CoreCompile.props | 15 + .../Core/Backlang.CoreCompile.targets | 55 +++ .../Core/Backlang.OuterBuild.targets | 29 ++ .../Core/Backlang.ProjectSystem.props | 43 ++ .../Core/Backlang.ProjectSystem.targets | 41 ++ .../Rules/Backlang.ProjectItemsSchema.xaml | 12 + NewSource/Backlang.Build.Tasks/Sdk/Sdk.props | 12 + .../Backlang.Build.Tasks/Sdk/Sdk.targets | 9 + .../Backlang.Build.Tasks/Tasks/Backlang.tasks | 18 + NewSource/Backlang.Build.Tasks/logo.png | Bin 0 -> 31321 bytes .../Attributes/BinaryOperatorInfoAttribute.cs | 15 + .../Core/Attributes/KeywordAttribute.cs | 12 + .../Core/Attributes/LexemeAttribute.cs | 12 + .../Core/Attributes/OperatorInfoAttribute.cs | 16 + .../PostUnaryOperatorInfoAttribute.cs | 15 + .../PreUnaryOperatorInfoAttribute.cs | 15 + .../Backlang.CodeAnalysis/Core/BaseLexer.cs | 66 +++ .../Backlang.CodeAnalysis/Core/ErrorID.cs | 37 ++ .../Core/LevensteinDistance.cs | 72 +++ .../Core/LocalizableString.cs | 54 +++ .../Core/ParsingHelpers.cs | 53 +++ .../Parsing/AST/Annotation.cs | 30 ++ .../Parsing/AST/CompilationUnit.cs | 24 + .../AST/Declarations/BitFieldDeclaration.cs | 19 + .../Declarations/BitFieldMemberDeclaration.cs | 33 ++ .../AST/Declarations/ClassDeclaration.cs | 26 ++ .../Declarations/ConstructorDeclaration.cs | 20 + .../AST/Declarations/DestructorDeclaration.cs | 20 + .../DiscriminatedUnionDeclaration.cs | 68 +++ .../AST/Declarations/EnumDeclaration.cs | 19 + .../AST/Declarations/EnumMemberDeclaration.cs | 21 + .../AST/Declarations/FunctionDeclaration.cs | 15 + .../Declarations/ImplementationDeclaration.cs | 56 +++ .../AST/Declarations/InterfaceDeclaration.cs | 25 ++ .../AST/Declarations/MacroBlockDeclaration.cs | 65 +++ .../AST/Declarations/MacroDeclaration.cs | 16 + .../AST/Declarations/ModuleDeclaration.cs | 18 + .../AST/Declarations/ParameterDeclaration.cs | 47 ++ .../AST/Declarations/StructDeclaration.cs | 26 ++ .../AST/Declarations/TypeAliasDeclaration.cs | 17 + .../AST/Declarations/TypeFieldDeclaration.cs | 13 + .../Declarations/TypeFunctionDeclaration.cs | 15 + .../AST/Declarations/TypeMemberDeclaration.cs | 143 ++++++ .../AST/Declarations/UnionDeclaration.cs | 21 + .../AST/Declarations/UnitDeclaration.cs | 16 + .../Parsing/AST/DocComment.cs | 26 ++ .../AST/Expressions/DefaultExpression.cs | 22 + .../AST/Expressions/GroupExpression.cs | 18 + .../Expressions/InitializerListExpression.cs | 30 ++ .../AST/Expressions/Match/MatchExpression.cs | 36 ++ .../AST/Expressions/Match/MatchRule.cs | 72 +++ .../Parsing/AST/Expressions/NameExpression.cs | 31 ++ .../Parsing/AST/Expressions/NoneExpression.cs | 11 + .../AST/Expressions/SizeOfExpression.cs | 19 + .../AST/Expressions/TypeofExpression.cs | 17 + .../Parsing/AST/Modifier.cs | 54 +++ .../Parsing/AST/Signature.cs | 54 +++ .../Parsing/AST/Statements/BreakStatement.cs | 14 + .../AST/Statements/ExpressionStatement.cs | 15 + .../Parsing/AST/Statements/IfStatement.cs | 24 + .../Parsing/AST/Statements/ImportStatement.cs | 18 + .../AST/Statements/Loops/ContinueStatement.cs | 14 + .../AST/Statements/Loops/DoWhileStatement.cs | 21 + .../AST/Statements/Loops/ForStatement.cs | 31 ++ .../AST/Statements/Loops/WhileStatement.cs | 16 + .../AST/Statements/MacroBlockStatement.cs | 48 ++ .../Parsing/AST/Statements/ReturnStatement.cs | 21 + .../Parsing/AST/Statements/Statement.cs | 34 ++ .../Parsing/AST/Statements/SwitchStatement.cs | 167 +++++++ .../Parsing/AST/Statements/ThrowStatement.cs | 21 + .../Parsing/AST/Statements/TryStatement.cs | 51 +++ .../AST/Statements/VariableStatement.cs | 46 ++ .../Parsing/AST/Symbols.cs | 35 ++ .../Parsing/AST/TypeLiteral.cs | 162 +++++++ .../Parsing/Expression.cs | 153 +++++++ .../Parsing/IParsePoint.cs | 8 + .../Parsing/LNodeExtensions.cs | 33 ++ .../Backlang.CodeAnalysis/Parsing/Lexer.cs | 416 ++++++++++++++++++ .../Backlang.CodeAnalysis/Parsing/Message.cs | 61 +++ .../Parsing/OperatorInfo.cs | 3 + .../Parsing/ParsePoints.cs | 7 + .../Parsing/Parser.Expressions.cs | 213 +++++++++ .../Parsing/Parser.ParsePoints.cs | 137 ++++++ .../Backlang.CodeAnalysis/Parsing/Parser.cs | 67 +++ .../Precedences/BinaryOpPrecedences.cs | 29 ++ .../Parsing/Precedences/UnaryOpPrecedences.cs | 14 + .../Parsing/SourceDocument.cs | 28 ++ .../Parsing/SyntaxTree.cs | 271 ++++++++++++ .../Backlang.CodeAnalysis/Parsing/Token.cs | 41 ++ .../Parsing/TokenIterator.cs | 107 +++++ .../Parsing/TokenType.cs | 260 +++++++++++ .../Parsing/TokenUtils.cs | 56 +++ .../Properties/Resources.Designer.cs | 350 +++++++++++++++ .../Properties/Resources.resx | 221 ++++++++++ .../Backlang.Runtime/Backlang.Runtime.csproj | 10 + .../CompilerService/MacroLibAttribute.cs | 5 + .../CompilerService/UnitAttribute.cs | 7 + .../CompilerService/UnitTypeAttribute.cs | 6 + .../Backlang.Runtime/Macros/BuiltInMacros.cs | 167 +++++++ .../Backlang.Runtime/Macros/QuoteMacro.cs | 309 +++++++++++++ NewSource/Backlang.Runtime/Result.cs | 25 ++ NewSource/Backlang.Runtime/Sealed.cs | 47 ++ NewSource/Backlang.Runtime/logo.png | Bin 0 -> 31321 bytes NewSource/Backlang.sln | 42 ++ NewSource/BacklangC/BacklangC.csproj | 30 ++ NewSource/BacklangC/Driver.cs | 99 +++++ NewSource/BacklangC/DriverSettings.cs | 36 ++ NewSource/BacklangC/OptimizationLevel.cs | 44 ++ NewSource/BacklangC/OptimizationPass.cs | 11 + NewSource/BacklangC/Optimizer.cs | 94 ++++ NewSource/BacklangC/Program.cs | 29 ++ NewSource/Directory.Build.props | 20 + NewSource/Directory.Build.targets | 10 + NewSource/README.md | 6 + NewSource/logo.png | Bin 0 -> 31321 bytes 119 files changed, 6110 insertions(+) create mode 100644 NewSource/Backlang.Build.Tasks/Backlang.Sdk.csproj create mode 100644 NewSource/Backlang.Build.Tasks/BuildTask.cs create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.Core.props create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.Core.targets create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.props create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.targets create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.OuterBuild.targets create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.props create mode 100644 NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.targets create mode 100644 NewSource/Backlang.Build.Tasks/Core/Rules/Backlang.ProjectItemsSchema.xaml create mode 100644 NewSource/Backlang.Build.Tasks/Sdk/Sdk.props create mode 100644 NewSource/Backlang.Build.Tasks/Sdk/Sdk.targets create mode 100644 NewSource/Backlang.Build.Tasks/Tasks/Backlang.tasks create mode 100644 NewSource/Backlang.Build.Tasks/logo.png create mode 100644 NewSource/Backlang.CodeAnalysis/Core/Attributes/BinaryOperatorInfoAttribute.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/Attributes/KeywordAttribute.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/Attributes/LexemeAttribute.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/Attributes/OperatorInfoAttribute.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/Attributes/PostUnaryOperatorInfoAttribute.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/Attributes/PreUnaryOperatorInfoAttribute.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/BaseLexer.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/ErrorID.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/LevensteinDistance.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/LocalizableString.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Core/ParsingHelpers.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Annotation.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/CompilationUnit.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldMemberDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ClassDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ConstructorDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DestructorDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DiscriminatedUnionDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumMemberDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/FunctionDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ImplementationDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/InterfaceDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroBlockDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ModuleDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ParameterDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/StructDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeAliasDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFieldDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFunctionDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeMemberDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnionDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnitDeclaration.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/DocComment.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/DefaultExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/GroupExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/InitializerListExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchRule.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NameExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NoneExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/SizeOfExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/TypeofExpression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Modifier.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Signature.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/BreakStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ExpressionStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/IfStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ImportStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ContinueStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/DoWhileStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ForStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/WhileStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/MacroBlockStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ReturnStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Statement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/SwitchStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ThrowStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/TryStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/VariableStatement.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/Symbols.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/AST/TypeLiteral.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Expression.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/IParsePoint.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/LNodeExtensions.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Lexer.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Message.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/OperatorInfo.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/ParsePoints.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Parser.Expressions.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Parser.ParsePoints.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Parser.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Precedences/BinaryOpPrecedences.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Precedences/UnaryOpPrecedences.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/SourceDocument.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/SyntaxTree.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/Token.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/TokenIterator.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/TokenType.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Parsing/TokenUtils.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Properties/Resources.Designer.cs create mode 100644 NewSource/Backlang.CodeAnalysis/Properties/Resources.resx create mode 100644 NewSource/Backlang.Runtime/Backlang.Runtime.csproj create mode 100644 NewSource/Backlang.Runtime/CompilerService/MacroLibAttribute.cs create mode 100644 NewSource/Backlang.Runtime/CompilerService/UnitAttribute.cs create mode 100644 NewSource/Backlang.Runtime/CompilerService/UnitTypeAttribute.cs create mode 100644 NewSource/Backlang.Runtime/Macros/BuiltInMacros.cs create mode 100644 NewSource/Backlang.Runtime/Macros/QuoteMacro.cs create mode 100644 NewSource/Backlang.Runtime/Result.cs create mode 100644 NewSource/Backlang.Runtime/Sealed.cs create mode 100644 NewSource/Backlang.Runtime/logo.png create mode 100644 NewSource/Backlang.sln create mode 100644 NewSource/BacklangC/BacklangC.csproj create mode 100644 NewSource/BacklangC/Driver.cs create mode 100644 NewSource/BacklangC/DriverSettings.cs create mode 100644 NewSource/BacklangC/OptimizationLevel.cs create mode 100644 NewSource/BacklangC/OptimizationPass.cs create mode 100644 NewSource/BacklangC/Optimizer.cs create mode 100644 NewSource/BacklangC/Program.cs create mode 100644 NewSource/Directory.Build.props create mode 100644 NewSource/Directory.Build.targets create mode 100644 NewSource/README.md create mode 100644 NewSource/logo.png diff --git a/NewSource/Backlang.Build.Tasks/Backlang.Sdk.csproj b/NewSource/Backlang.Build.Tasks/Backlang.Sdk.csproj new file mode 100644 index 0000000..bf7c346 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Backlang.Sdk.csproj @@ -0,0 +1,49 @@ + + + + true + Backlang.Build.Tasks + Backlang.Build.Tasks + true + true + + + + false + false + true + Tasks + true + + + + Backlang.Sdk + 0.1.5 + MSBuildSdk + msbuild sdk Backlang + MSBuild SDK for Backlang + true + https://github.com/furesoft/compiler-test + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/BuildTask.cs b/NewSource/Backlang.Build.Tasks/BuildTask.cs new file mode 100644 index 0000000..bbbaef3 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/BuildTask.cs @@ -0,0 +1,59 @@ +using Backlang.Codeanalysis.Parsing; +using Microsoft.Build.Framework; +using BacklangC; +using Task = Microsoft.Build.Utilities.Task; + +namespace Backlang.Build.Tasks; + +public class BuildTask : Task +{ + [System.ComponentModel.DataAnnotations.Required] + public ITaskItem[] SourceFiles { get; set; } + + [System.ComponentModel.DataAnnotations.Required] + public string OutputPath { get; set; } + + [System.ComponentModel.DataAnnotations.Required] + public ITaskItem[] ReferencePaths { get; set; } + + public string OptimizeLevel { get; set; } + public bool DebugSymbols { get; set; } + public string Configuration { get; set; } + public string Version { get; set; } + public string RootNamespace { get; set; } + + public override bool Execute() + { + var driver = Driver.Create(new DriverSettings + { + OutputPath = OutputPath, + RootNamespace = RootNamespace, + Sources = SourceFiles.Select(_ => _.ItemSpec).ToArray(), + OptimizeLevel = OptimizeLevel, + DebugSymbols = DebugSymbols, + IsDebug = Configuration == "Debug", + Version = Version + }); + + driver.Compile(); + + foreach (var message in driver.Messages) + { + switch (message.Severity) + { + case MessageSeverity.Error: + Log.LogError(null, null, null, + file: message.Document.FileName, message.Range.Start.Line, message.Range.Start.Column, + message.Range.End.Line, message.Range.End.Column, message.Text); + break; + case MessageSeverity.Warning: + Log.LogWarning(null, null, null, + file: message.Document.FileName, message.Range.Start.Line, message.Range.Start.Column, + message.Range.End.Line, message.Range.End.Column, message.Text); + break; + } + } + + return true; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.Core.props b/NewSource/Backlang.Build.Tasks/Core/Backlang.Core.props new file mode 100644 index 0000000..be921ab --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.Core.props @@ -0,0 +1,9 @@ + + + + .back + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.Core.targets b/NewSource/Backlang.Build.Tasks/Core/Backlang.Core.targets new file mode 100644 index 0000000..ac0243c --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.Core.targets @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.props b/NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.props new file mode 100644 index 0000000..35f6145 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.props @@ -0,0 +1,15 @@ + + + + $(MSBuildProjectName) + + + + O2 + + + + true + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.targets b/NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.targets new file mode 100644 index 0000000..a261614 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.CoreCompile.targets @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)"/> + + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.OuterBuild.targets b/NewSource/Backlang.Build.Tasks/Core/Backlang.OuterBuild.targets new file mode 100644 index 0000000..3db17fc --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.OuterBuild.targets @@ -0,0 +1,29 @@ + + + + + + + + Publish + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.props b/NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.props new file mode 100644 index 0000000..a3a98b4 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.props @@ -0,0 +1,43 @@ + + + + + Properties + false + Backlang + Backlang + Camel + Private + Declarations + + + + + {13B669BE-BB05-4DDF-9536-439F39A36129} + + + + + $(DefaultProjectTypeGuid) + $(DefaultProjectTypeGuid) + $(DefaultProjectTypeGuid) + $(DefaultProjectTypeGuid) + + + + + CSharp + C# + {9A19103F-16F7-4668-BE54-9A1E7A4F7556} + {694DD9B6-B865-4C5B-AD85-86356E9C88DC} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + {FAE04EC1-301F-11D3-BF4B-00C04F79EFBC} + {FAE04EC1-301F-11D3-BF4B-00C04F79EFBC} + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.targets b/NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.targets new file mode 100644 index 0000000..3b5983d --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Backlang.ProjectSystem.targets @@ -0,0 +1,41 @@ + + + + + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\Managed + $(DesignTimeExtensionsPath)\Microsoft.Managed.DesignTime.targets + + + + + + + + + + + + + + + File + + + + BrowseObject + + + + + + + + + + + <_CompilerCommandLineArgs Include="@(MscCommandLineArgs)"/> + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Core/Rules/Backlang.ProjectItemsSchema.xaml b/NewSource/Backlang.Build.Tasks/Core/Rules/Backlang.ProjectItemsSchema.xaml new file mode 100644 index 0000000..242ad40 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Core/Rules/Backlang.ProjectItemsSchema.xaml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Sdk/Sdk.props b/NewSource/Backlang.Build.Tasks/Sdk/Sdk.props new file mode 100644 index 0000000..b2cee75 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Sdk/Sdk.props @@ -0,0 +1,12 @@ + + + + + true + + + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Sdk/Sdk.targets b/NewSource/Backlang.Build.Tasks/Sdk/Sdk.targets new file mode 100644 index 0000000..a76cb6b --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Sdk/Sdk.targets @@ -0,0 +1,9 @@ + + + + $([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)', '..\Core\Backlang.Runtime.targets')) + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/Tasks/Backlang.tasks b/NewSource/Backlang.Build.Tasks/Tasks/Backlang.tasks new file mode 100644 index 0000000..b083600 --- /dev/null +++ b/NewSource/Backlang.Build.Tasks/Tasks/Backlang.tasks @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NewSource/Backlang.Build.Tasks/logo.png b/NewSource/Backlang.Build.Tasks/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..557ebd34254b355fc48dc18debe824d07ec6f5b5 GIT binary patch literal 31321 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 RWX#0F#PFQKhm(#E{|_JJ(U|}M literal 0 HcmV?d00001 diff --git a/NewSource/Backlang.CodeAnalysis/Core/Attributes/BinaryOperatorInfoAttribute.cs b/NewSource/Backlang.CodeAnalysis/Core/Attributes/BinaryOperatorInfoAttribute.cs new file mode 100644 index 0000000..d5f94dc --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/Attributes/BinaryOperatorInfoAttribute.cs @@ -0,0 +1,15 @@ +using Backlang.Codeanalysis.Parsing.Precedences; + +namespace Backlang.Codeanalysis.Core.Attributes; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] +public sealed class BinaryOperatorInfoAttribute : OperatorInfoAttribute +{ + public BinaryOperatorInfoAttribute(int precedence) : base(precedence, false, false) + { + } + + public BinaryOperatorInfoAttribute(BinaryOpPrecedences precedence) : this((int)precedence) + { + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/Attributes/KeywordAttribute.cs b/NewSource/Backlang.CodeAnalysis/Core/Attributes/KeywordAttribute.cs new file mode 100644 index 0000000..e328055 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/Attributes/KeywordAttribute.cs @@ -0,0 +1,12 @@ +namespace Backlang.Codeanalysis.Core.Attributes; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] +public sealed class KeywordAttribute : Attribute +{ + public KeywordAttribute(string keyword) + { + Keyword = keyword; + } + + public string Keyword { get; set; } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/Attributes/LexemeAttribute.cs b/NewSource/Backlang.CodeAnalysis/Core/Attributes/LexemeAttribute.cs new file mode 100644 index 0000000..5eccc9d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/Attributes/LexemeAttribute.cs @@ -0,0 +1,12 @@ +namespace Backlang.Codeanalysis.Core.Attributes; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] +public sealed class LexemeAttribute : Attribute +{ + public LexemeAttribute(string lexeleme) + { + Lexeme = lexeleme; + } + + public string Lexeme { get; set; } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/Attributes/OperatorInfoAttribute.cs b/NewSource/Backlang.CodeAnalysis/Core/Attributes/OperatorInfoAttribute.cs new file mode 100644 index 0000000..6e39a7d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/Attributes/OperatorInfoAttribute.cs @@ -0,0 +1,16 @@ +namespace Backlang.Codeanalysis.Core.Attributes; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] +public class OperatorInfoAttribute : Attribute +{ + public OperatorInfoAttribute(int precedence, bool isUnary, bool isPostUnary) + { + Precedence = precedence; + IsUnary = isUnary; + IsPostUnary = isPostUnary; + } + + public bool IsPostUnary { get; set; } + public bool IsUnary { get; set; } + public int Precedence { get; set; } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/Attributes/PostUnaryOperatorInfoAttribute.cs b/NewSource/Backlang.CodeAnalysis/Core/Attributes/PostUnaryOperatorInfoAttribute.cs new file mode 100644 index 0000000..9c0c054 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/Attributes/PostUnaryOperatorInfoAttribute.cs @@ -0,0 +1,15 @@ +using Backlang.Codeanalysis.Parsing.Precedences; + +namespace Backlang.Codeanalysis.Core.Attributes; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] +public sealed class PostUnaryOperatorInfoAttribute : OperatorInfoAttribute +{ + public PostUnaryOperatorInfoAttribute(int precedence) : base(precedence, true, true) + { + } + + public PostUnaryOperatorInfoAttribute(UnaryOpPrecedences precedence) : this((int)precedence) + { + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/Attributes/PreUnaryOperatorInfoAttribute.cs b/NewSource/Backlang.CodeAnalysis/Core/Attributes/PreUnaryOperatorInfoAttribute.cs new file mode 100644 index 0000000..26a95cc --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/Attributes/PreUnaryOperatorInfoAttribute.cs @@ -0,0 +1,15 @@ +using Backlang.Codeanalysis.Parsing.Precedences; + +namespace Backlang.Codeanalysis.Core.Attributes; + +[AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] +public sealed class PreUnaryOperatorInfoAttribute : OperatorInfoAttribute +{ + public PreUnaryOperatorInfoAttribute(int precedence) : base(precedence, true, false) + { + } + + public PreUnaryOperatorInfoAttribute(UnaryOpPrecedences precedence) : this((int)precedence) + { + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/BaseLexer.cs b/NewSource/Backlang.CodeAnalysis/Core/BaseLexer.cs new file mode 100644 index 0000000..ad4681b --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/BaseLexer.cs @@ -0,0 +1,66 @@ +using Backlang.Codeanalysis.Parsing; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Core; + +public abstract class BaseLexer +{ + protected int _column = 1; + protected SourceFile _document; + protected int _line = 1; + protected int _position; + public List Messages = new(); + + public List Tokenize(SourceFile document) + { + _document = document; + + var tokens = new List(); + + Token newToken; + do + { + newToken = NextToken(); + + tokens.Add(newToken); + } while (newToken.Type != TokenType.EOF); + + return tokens; + } + + protected int Advance() + { + return ++_position; + } + + protected char Current() + { + if (_position >= _document.Text.Count) + { + return '\0'; + } + + return _document.Text[_position]; + } + + protected abstract Token NextToken(); + + protected char Peek(int offset = 0) + { + if (_position + offset >= _document.Text.Count) + { + return '\0'; + } + + return _document.Text[_position + offset]; + } + + protected void ReportError() + { + _column++; + + var range = SourceRange.New(_document, new IndexRange(_position, 1)); + Messages.Add(Message.Error(new LocalizableString(ErrorID.UnknownCharacter, Current().ToString()), range)); + Advance(); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/ErrorID.cs b/NewSource/Backlang.CodeAnalysis/Core/ErrorID.cs new file mode 100644 index 0000000..1c164e2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/ErrorID.cs @@ -0,0 +1,37 @@ +namespace Backlang.Codeanalysis.Core; + +public enum ErrorID +{ + UnexpecedType = 0001, + InvalidModifierCombination = 0002, + UnknownCharacter = 0003, + UnterminatedCharLiteral = 0004, + UnknownExpression = 0005, + UnknownLiteral = 0006, + ForbiddenTrailingComma = 0007, + BitfieldNotLiteral = 0008, + UnexpecedTypeMember = 0009, + ExpectedTypeLiteral = 0010, + UnknownSwitchOption = 0011, + NoCatchBlock = 0012, + EmptyFile = 0013, + ExpectedIdentifier = 0014, + UnterminatedStringLiteral = 0015, + NotClosedMultilineComment = 0016, + Expected = 0017, + DuplicateModifier = 0018, + NamespaceAlreadyImported = 0019, + RunnableTypeButNoEntrypoint = 0020, + CannotBeFoundDidYouMean = 0021, + CannotImplementTypeNotFound = 0022, + CannotImplementUnitType = 0023, + AlreadyDeclared = 0024, + TypeMismatch = 0025, + UnitTypeMismatch = 0026, + CannotBeResolved = 0027, + CannotFindFunction = 0028, + TargetNotFound = 0029, + NotDefined = 0030, + CannotDeduceType = 31, + DeducingTypeNotPossible = 32 +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/LevensteinDistance.cs b/NewSource/Backlang.CodeAnalysis/Core/LevensteinDistance.cs new file mode 100644 index 0000000..c0eb191 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/LevensteinDistance.cs @@ -0,0 +1,72 @@ +namespace Backlang.Codeanalysis.Core; + +public static class LevensteinDistance +{ + public static int Calculate(string source, string target) + { + if (string.IsNullOrEmpty(source)) + { + return string.IsNullOrEmpty(target) ? 0 : target.Length; + } + + if (string.IsNullOrEmpty(target)) + { + return source.Length; + } + + if (source.Length > target.Length) + { + (source, target) = (target, source); + } + + var m = target.Length; + var n = source.Length; + var distance = new int[2, m + 1]; + // Initialize the distance matrix + for (var j = 1; j <= m; j++) + { + distance[0, j] = j; + } + + var currentRow = 0; + for (var i = 1; i <= n; ++i) + { + currentRow = i & 1; + distance[currentRow, 0] = i; + var previousRow = currentRow ^ 1; + for (var j = 1; j <= m; j++) + { + var cost = target[j - 1] == source[i - 1] ? 0 : 1; + distance[currentRow, j] = Math.Min(Math.Min( + distance[previousRow, j] + 1, + distance[currentRow, j - 1] + 1), + distance[previousRow, j - 1] + cost); + } + } + + return distance[currentRow, m]; + } + + public static string Suggest(string source, IEnumerable possibilities) + { + var lastDistance = 10; + var lastSuggestion = string.Empty; + + foreach (var str in possibilities) + { + if (str == "Main") + { + continue; + } + + var distance = Calculate(source, str); + if (distance <= lastDistance) + { + lastDistance = distance; + lastSuggestion = str; + } + } + + return lastSuggestion; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/LocalizableString.cs b/NewSource/Backlang.CodeAnalysis/Core/LocalizableString.cs new file mode 100644 index 0000000..d7d330a --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/LocalizableString.cs @@ -0,0 +1,54 @@ +using Backlang.Codeanalysis.Properties; +using System.Resources; + +namespace Backlang.Codeanalysis.Core; + +public readonly struct LocalizableString +{ + public readonly ErrorID ErrorID; + public readonly string[] Arguments; + public readonly string FallbackValue; + + private static readonly ResourceManager _resourceManager = + new("Backlang.CodeAnalysisProperties.Resources", typeof(Resources).Assembly); + + public LocalizableString(ErrorID errorID, params string[] arguments) + { + ErrorID = errorID; + Arguments = arguments; + FallbackValue = null; + } + + public LocalizableString(ErrorID errorID) : this() + { + ErrorID = errorID; + Arguments = new[] { "NO_VALUE" }; + } + + public LocalizableString(string fallbackValue) : this() + { + FallbackValue = fallbackValue; + } + + public static implicit operator string(LocalizableString lstr) + { + if (!string.IsNullOrEmpty(lstr.FallbackValue)) + { + return lstr.FallbackValue; + } + + var resourceID = $"BL({(int)lstr.ErrorID:D4})"; + + return string.Format(resourceID + ": " + _resourceManager.GetString(resourceID), lstr.Arguments); + } + + public static implicit operator LocalizableString(ErrorID id) + { + return new LocalizableString(id); + } + + public static implicit operator LocalizableString(string message) + { + return new LocalizableString(message); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Core/ParsingHelpers.cs b/NewSource/Backlang.CodeAnalysis/Core/ParsingHelpers.cs new file mode 100644 index 0000000..fb106b1 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Core/ParsingHelpers.cs @@ -0,0 +1,53 @@ +using Backlang.Codeanalysis.Parsing; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Core; + +internal static class ParsingHelpers +{ + public static LNodeList ParseSeperated( + Parser parser, + TokenType terminator, + TokenType seperator = TokenType.Comma, bool consumeTerminator = true) + where T : IParsePoint + { + if (parser.Iterator.IsMatch(terminator)) + { + parser.Iterator.Match(terminator); + return LNodeList.Empty; + } + + var list = new LNodeList(); + do + { + list.Add(T.Parse(parser.Iterator, parser)); + + if (parser.Iterator.IsMatch(seperator) && parser.Iterator.Peek(1).Type == terminator) + { + parser.AddError(ErrorID.ForbiddenTrailingComma); + parser.Iterator.Match(seperator); + } + } while (parser.Iterator.ConsumeIfMatch(seperator)); + + if (consumeTerminator) + { + parser.Iterator.Match(terminator); + } + + return list; + } + + public static LNodeList ParseUntil(Parser parser, TokenType terminator) + where T : IParsePoint + { + var members = new LNodeList(); + while (parser.Iterator.Current.Type != terminator) + { + members.Add(T.Parse(parser.Iterator, parser)); + } + + parser.Iterator.Match(terminator); + + return members; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Annotation.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Annotation.cs new file mode 100644 index 0000000..9bdf5fa --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Annotation.cs @@ -0,0 +1,30 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public sealed class Annotation +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var atToken = iterator.Match(TokenType.At); + var call = Expression.Parse(parser); + + return SyntaxTree.Annotation(call).WithRange(atToken, iterator.Prev); + } + + public static bool TryParse(Parser parser, out LNodeList node) + { + var annotations = new LNodeList(); + var isAnnotation = () => + parser.Iterator.IsMatch(TokenType.At) && parser.Iterator.Peek(1).Type == TokenType.Identifier; + + while (isAnnotation()) + { + annotations.Add(Parse(parser.Iterator, parser)); + } + + node = annotations; + + return annotations.Count > 0; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/CompilationUnit.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/CompilationUnit.cs new file mode 100644 index 0000000..6c4a32d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/CompilationUnit.cs @@ -0,0 +1,24 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public sealed class CompilationUnit +{ + public LNodeList Body { get; set; } = new(); + public SourceFile Document { get; internal set; } + public List Messages { get; set; } = new(); + + public static CompilationUnit FromFile(string filename) + { + var document = new SourceDocument(filename); + + return Parser.Parse(document); + } + + public static CompilationUnit FromText(string text) + { + var document = new SourceDocument("inline.back", text); + + return Parser.Parse(document); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldDeclaration.cs new file mode 100644 index 0000000..cd73678 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldDeclaration.cs @@ -0,0 +1,19 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class BitFieldDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var nameToken = iterator.Match(TokenType.Identifier); + + iterator.Match(TokenType.OpenCurly); + + var members = ParsingHelpers.ParseSeperated(parser, TokenType.CloseCurly); + + return SyntaxTree.Bitfield(nameToken, members).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldMemberDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldMemberDeclaration.cs new file mode 100644 index 0000000..7d25448 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/BitFieldMemberDeclaration.cs @@ -0,0 +1,33 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class BitFieldMemberDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + Token nameToken; + if (iterator.Current.Type == TokenType.Identifier) + { + nameToken = iterator.Current; + + iterator.NextToken(); + } + else + { + nameToken = iterator.NextToken(); + } + + iterator.Match(TokenType.EqualsToken); + + var value = Expression.Parse(parser); + + if (!value[0].HasValue) + { + parser.AddError(ErrorID.BitfieldNotLiteral, value.Range); + } + + return SyntaxTree.Factory.Tuple(SyntaxTree.Factory.Id(nameToken.Text).WithRange(nameToken), value); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ClassDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ClassDeclaration.cs new file mode 100644 index 0000000..e261976 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ClassDeclaration.cs @@ -0,0 +1,26 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class ClassDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + var nameToken = iterator.Match(TokenType.Identifier); + var inheritances = new LNodeList(); + + if (iterator.ConsumeIfMatch(TokenType.Colon)) + { + inheritances = Expression.ParseList(parser, TokenType.OpenCurly, false); + } + + iterator.Match(TokenType.OpenCurly); + + var members = ParsingHelpers.ParseUntil(parser, TokenType.CloseCurly); + + return SyntaxTree.Class(nameToken, inheritances, members).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ConstructorDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ConstructorDeclaration.cs new file mode 100644 index 0000000..a951867 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ConstructorDeclaration.cs @@ -0,0 +1,20 @@ +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public class ConstructorDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + iterator.Match(TokenType.OpenParen); + + var parameters = ParameterDeclaration.ParseList(parser); + + var code = Statement.ParseBlock(parser); + + return SyntaxTree.Constructor(parameters, code).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DestructorDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DestructorDeclaration.cs new file mode 100644 index 0000000..ab224d4 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DestructorDeclaration.cs @@ -0,0 +1,20 @@ +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public class DestructorDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + iterator.Match(TokenType.OpenParen); + + var parameters = ParameterDeclaration.ParseList(parser); + + var code = Statement.ParseBlock(parser); + + return SyntaxTree.Destructor(parameters, code).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DiscriminatedUnionDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DiscriminatedUnionDeclaration.cs new file mode 100644 index 0000000..2c34457 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/DiscriminatedUnionDeclaration.cs @@ -0,0 +1,68 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public class DiscriminatedUnionDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var nametoken = iterator.Match(TokenType.Identifier); + iterator.Match(TokenType.EqualsToken); + + var types = new LNodeList(); + + do + { + //ToDo: Refactor To Helper Method: RepeatUntil + var from = iterator.Current; + iterator.Match(TokenType.Pipe); + types.Add(ParseType(iterator, parser).WithRange(from, iterator.Prev)); + } while (iterator.IsMatch(TokenType.Pipe)); + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.DiscriminatedUnion(nametoken, types).WithRange(keywordToken, iterator.Prev); + } + + public static LNode ParseType(TokenIterator iterator, Parser parser) + { + var nameToken = iterator.Match(TokenType.Identifier); + + iterator.Match(TokenType.OpenParen); + + var parameters = ParseParameterDeclarations(iterator, parser); + + iterator.Match(TokenType.CloseParen); + + return SyntaxTree.DiscriminatedType(nameToken, parameters); + } + + public static LNodeList ParseParameterDeclarations(TokenIterator iterator, Parser parser) + { + var parameters = new LNodeList(); + while (iterator.Current.Type != TokenType.CloseParen) + { + while (iterator.Current.Type != TokenType.Comma && iterator.Current.Type != TokenType.CloseParen) + { + var isMutable = iterator.ConsumeIfMatch(TokenType.Mutable); + + var parameter = ParameterDeclaration.Parse(iterator, parser); + + if (iterator.Current.Type == TokenType.Comma) + { + iterator.NextToken(); + } + + if (isMutable) + { + parameter = parameter.PlusAttr(SyntaxTree.Factory.Id(Symbols.Mutable)); + } + + parameters.Add(parameter); + } + } + + return parameters; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumDeclaration.cs new file mode 100644 index 0000000..0294bb2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumDeclaration.cs @@ -0,0 +1,19 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class EnumDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var nameToken = iterator.Match(TokenType.Identifier); + + iterator.Match(TokenType.OpenCurly); + + var members = ParsingHelpers.ParseSeperated(parser, TokenType.CloseCurly); + + return SyntaxTree.Enum(LNode.Id(nameToken.Text), members).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumMemberDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumMemberDeclaration.cs new file mode 100644 index 0000000..2a458b7 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/EnumMemberDeclaration.cs @@ -0,0 +1,21 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public class EnumMemberDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + _ = Annotation.TryParse(parser, out var annotations); + + var memberNameToken = iterator.Match(TokenType.Identifier); + LNode value = LNode.Missing; + + if (iterator.ConsumeIfMatch(TokenType.EqualsToken)) + { + value = parser.ParsePrimary(); + } + + return SyntaxTree.Factory.Var(LNode.Missing, LNode.Id(memberNameToken.Text), value).PlusAttrs(annotations); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/FunctionDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/FunctionDeclaration.cs new file mode 100644 index 0000000..bff5f81 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/FunctionDeclaration.cs @@ -0,0 +1,15 @@ +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class FunctionDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var signature = Signature.Parse(parser); + + return signature.PlusArg(Statement.ParseBlock(parser)).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ImplementationDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ImplementationDeclaration.cs new file mode 100644 index 0000000..8814246 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ImplementationDeclaration.cs @@ -0,0 +1,56 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public class ImplementationDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var targets = new LNodeList(); + + while (iterator.Current.Type != TokenType.OpenCurly && !parser.Iterator.IsMatch(TokenType.EOF)) + { + if (iterator.Peek(1).Type == TokenType.RangeOperator) + { + targets.Add(Expression.Parse(parser)); + } + else + { + targets.Add(TypeLiteral.Parse(iterator, parser)); + } + + if (iterator.Current.Type != TokenType.OpenCurly) + { + iterator.Match(TokenType.Comma); + } + } + + LNode target; + if (targets.Count == 1) + { + target = targets[0]; + } + else + { + //ToDo: need to be fixed + target = LNode.Call(Symbols.ToExpand, targets); + } + + iterator.Match(TokenType.OpenCurly); + + LNodeList body = new(); + while (!parser.Iterator.IsMatch(TokenType.EOF) && iterator.Current.Type != TokenType.CloseCurly) + { + _ = Annotation.TryParse(parser, out var annotations); + _ = Modifier.TryParse(parser, out var modifiers); + + body.Add(parser.InvokeParsePoint(parser.DeclarationParsePoints).PlusAttrs(annotations) + .PlusAttrs(modifiers)); + } + + iterator.Match(TokenType.CloseCurly); + + return SyntaxTree.ImplDecl(target, body).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/InterfaceDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/InterfaceDeclaration.cs new file mode 100644 index 0000000..276fe05 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/InterfaceDeclaration.cs @@ -0,0 +1,25 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class InterfaceDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var nameToken = iterator.Match(TokenType.Identifier); + var inheritances = new LNodeList(); + + if (iterator.ConsumeIfMatch(TokenType.Colon)) + { + inheritances = Expression.ParseList(parser, TokenType.OpenCurly, false); + } + + iterator.Match(TokenType.OpenCurly); + + var members = ParsingHelpers.ParseUntil(parser, TokenType.CloseCurly); + + return SyntaxTree.Interface(nameToken, inheritances, members).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroBlockDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroBlockDeclaration.cs new file mode 100644 index 0000000..dcfb17a --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroBlockDeclaration.cs @@ -0,0 +1,65 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class MacroBlockDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var nameExpression = LNode.Id(iterator.Prev.Text).WithRange(iterator.Current); + + var pp = parser.DeclarationParsePoints; + + foreach (var p in parser.StatementParsePoints) + { + if (pp.ContainsKey(p.Key)) + { + continue; + } + + pp.Add(p.Key, p.Value); + } + + if (iterator.Current.Type == TokenType.OpenParen) + { + iterator.NextToken(); + + var arguments = Expression.ParseList(parser, TokenType.CloseParen); + + if (iterator.Current.Type == TokenType.OpenCurly) + { + iterator.NextToken(); + //custom code block with arguments + + var body = parser.InvokeDeclarationParsePoints(TokenType.CloseCurly, pp); + iterator.Match(TokenType.CloseCurly); + + arguments = arguments.Add(LNode.Call(CodeSymbols.Braces, body)); + + return SyntaxTree.Factory.Call(nameExpression, arguments).SetStyle(NodeStyle.StatementBlock) + .SetStyle(NodeStyle.Special).WithRange(nameExpression.Range.StartIndex, iterator.Prev.End); + } + + parser.Iterator.Match(TokenType.Semicolon); + + return LNode.Call(nameExpression, arguments); + } + + if (iterator.Current.Type == TokenType.OpenCurly) + { + iterator.NextToken(); + + //custom code block without arguments + var body = parser.InvokeDeclarationParsePoints(TokenType.CloseCurly, pp); + iterator.Match(TokenType.CloseCurly); + + var arguments = LNode.List(LNode.Missing); + arguments = arguments.Add(LNode.Call(CodeSymbols.Braces, body)); + + return SyntaxTree.Factory.Call(nameExpression, arguments).SetStyle(NodeStyle.StatementBlock) + .SetStyle(NodeStyle.Special).WithRange(nameExpression.Range.StartIndex, iterator.Prev.End); + } + + return LNode.Missing; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroDeclaration.cs new file mode 100644 index 0000000..606015d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/MacroDeclaration.cs @@ -0,0 +1,16 @@ +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class MacroDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var signature = Signature.Parse(parser); + + return signature.WithTarget(Symbols.Macro).PlusArg(LNode.Call(CodeSymbols.Braces, Statement.ParseBlock(parser)) + .SetStyle(NodeStyle.StatementBlock)).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ModuleDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ModuleDeclaration.cs new file mode 100644 index 0000000..0dea4c2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ModuleDeclaration.cs @@ -0,0 +1,18 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class ModuleDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + //module + //module . + var keywordToken = iterator.Prev; + var tree = SyntaxTree.Module(Expression.Parse(parser)); + + iterator.Match(TokenType.Semicolon); + + return tree.WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ParameterDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ParameterDeclaration.cs new file mode 100644 index 0000000..87440f2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/ParameterDeclaration.cs @@ -0,0 +1,47 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class ParameterDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + _ = Annotation.TryParse(parser, out var annotations); + + var keywordToken = iterator.Current; + var name = iterator.Match(TokenType.Identifier); + + var assertNotNull = false; + if (iterator.ConsumeIfMatch(TokenType.Exclamation)) + { + assertNotNull = true; + } + + iterator.Match(TokenType.Colon); + + var type = TypeLiteral.Parse(iterator, parser); + + LNode defaultValue = LNode.Missing; + + if (iterator.Current.Type == TokenType.EqualsToken) + { + iterator.NextToken(); + + defaultValue = Expression.Parse(parser); + } + + if (assertNotNull) + { + annotations = annotations.Add(LNode.Id(Symbols.AssertNonNull)); + } + + return SyntaxTree.Factory.Var(type, name.Text, defaultValue).PlusAttrs(annotations) + .WithRange(keywordToken, iterator.Prev); + } + + public static LNodeList ParseList(Parser parser) + { + return ParsingHelpers.ParseSeperated(parser, TokenType.CloseParen); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/StructDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/StructDeclaration.cs new file mode 100644 index 0000000..90ed42a --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/StructDeclaration.cs @@ -0,0 +1,26 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class StructDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var name = iterator.Match(TokenType.Identifier); + var inheritances = new LNodeList(); + + if (iterator.ConsumeIfMatch(TokenType.Colon)) + { + inheritances = Expression.ParseList(parser, TokenType.OpenCurly, false); + } + + iterator.Match(TokenType.OpenCurly); + + var members = ParsingHelpers.ParseUntil(parser, TokenType.CloseCurly); + + return SyntaxTree.Struct(name, inheritances, members) + .WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeAliasDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeAliasDeclaration.cs new file mode 100644 index 0000000..9ca344a --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeAliasDeclaration.cs @@ -0,0 +1,17 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class TypeAliasDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + // using as + var keywordToken = iterator.Prev; + var expr = Expression.Parse(parser); // because 'as' is binary so i32 as int resolves to as(i32, int) + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.Using(expr).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFieldDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFieldDeclaration.cs new file mode 100644 index 0000000..cf1cafd --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFieldDeclaration.cs @@ -0,0 +1,13 @@ +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class TypeFieldDeclaration +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + iterator.Match(TokenType.Let); + return VariableStatement.Parse(iterator, parser); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFunctionDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFunctionDeclaration.cs new file mode 100644 index 0000000..1c180a0 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeFunctionDeclaration.cs @@ -0,0 +1,15 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class TypeFunctionDeclaration +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Match(TokenType.Function); + var result = Signature.Parse(parser); + iterator.Match(TokenType.Semicolon); + + return result.WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeMemberDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeMemberDeclaration.cs new file mode 100644 index 0000000..8976e7a --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/TypeMemberDeclaration.cs @@ -0,0 +1,143 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class TypeMemberDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + _ = Annotation.TryParse(parser, out var annotations); + _ = Modifier.TryParse(parser, out var modifiers); + + LNode declaration = LNode.Missing; + + if (iterator.IsMatch(TokenType.Function)) + { + declaration = ParseFunction(iterator, parser); + } + else if (iterator.IsMatch(TokenType.Property)) + { + declaration = ParseProperty(iterator, parser); + } + else if (iterator.IsMatch(TokenType.Let)) + { + declaration = ParseField(iterator, parser); + } + else + { + var range = new SourceRange(parser.Document, iterator.Current.Start, iterator.Current.Text.Length); + + parser.AddError(new LocalizableString(ErrorID.UnexpecedTypeMember, iterator.Current.Text), range); + iterator.NextToken(); + } + + return declaration.PlusAttrs(annotations).PlusAttrs(modifiers); + } + + public static LNode ParseField(TokenIterator iterator, Parser parser) + { + iterator.Match(TokenType.Let); + return VariableStatement.Parse(iterator, parser); + } + + public static LNode ParseFunction(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Match(TokenType.Function); + var result = Signature.Parse(parser); + iterator.Match(TokenType.Semicolon); + + return result.WithRange(keywordToken, iterator.Prev); + } + + public static LNode ParseProperty(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Match(TokenType.Property); + LNode type = LNode.Missing; + LNode value = LNode.Missing; + var nameToken = iterator.Match(TokenType.Identifier); + var name = LNode.Id(nameToken.Text); + + if (iterator.IsMatch(TokenType.Colon)) + { + iterator.NextToken(); + + type = TypeLiteral.Parse(iterator, parser); + } + + iterator.Match(TokenType.OpenCurly); + + LNode getter = LNode.Missing; + LNode setter = LNode.Missing; + + var needModifier = false; + + _ = Modifier.TryParse(parser, out var modifier); + if (iterator.IsMatch(TokenType.Get)) + { + iterator.NextToken(); + var args = LNode.List(); + if (iterator.IsMatch(TokenType.Semicolon)) + { + iterator.NextToken(); + } + else + { + args.Add(Statement.ParseBlock(parser)); + } + + getter = LNode.Call(CodeSymbols.get, args).WithAttrs(modifier); + needModifier = true; + } + + if (needModifier) + { + _ = Modifier.TryParse(parser, out modifier); + } + + if (iterator.IsMatch(TokenType.Set)) + { + iterator.NextToken(); + var args = LNode.List(); + if (iterator.IsMatch(TokenType.Semicolon)) + { + iterator.NextToken(); + } + else + { + args.Add(Statement.ParseBlock(parser)); + } + + setter = LNode.Call(CodeSymbols.set, args).WithAttrs(modifier); + } + else if (iterator.IsMatch(TokenType.Init)) + { + iterator.NextToken(); + var args = LNode.List(); + if (iterator.IsMatch(TokenType.Semicolon)) + { + iterator.NextToken(); + } + else + { + args.Add(Statement.ParseBlock(parser)); + } + + setter = LNode.Call(Symbols.Init, args).WithAttrs(modifier); + } + + iterator.Match(TokenType.CloseCurly); + + if (iterator.IsMatch(TokenType.EqualsToken)) + { + iterator.NextToken(); + + value = Expression.Parse(parser); + + iterator.Match(TokenType.Semicolon); + } + + return SyntaxTree.Property(type, name, getter, setter, value).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnionDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnionDeclaration.cs new file mode 100644 index 0000000..6f8c4b8 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnionDeclaration.cs @@ -0,0 +1,21 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public sealed class UnionDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + var nameToken = iterator.Match(TokenType.Identifier); + + iterator.Match(TokenType.OpenCurly); + + var members = ParsingHelpers.ParseSeperated(parser, TokenType.CloseCurly); + + return SyntaxTree.Union(nameToken.Text, members).WithRange(keywordToken, iterator.Current); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnitDeclaration.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnitDeclaration.cs new file mode 100644 index 0000000..e9a2867 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Declarations/UnitDeclaration.cs @@ -0,0 +1,16 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Declarations; + +public class UnitDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var nameToken = iterator.Match(TokenType.Identifier); + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.UnitDeclaration(nameToken).WithRange(keywordToken, nameToken); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/DocComment.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/DocComment.cs new file mode 100644 index 0000000..0c290c7 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/DocComment.cs @@ -0,0 +1,26 @@ +using Loyc; +using Loyc.Syntax; +using System.Xml; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public sealed class DocComment +{ + public static LNode Parse(Parser parser) + { + var comment = parser.Iterator.Match(TokenType.DocComment); + var xmlDocument = new XmlDocument(); + xmlDocument.LoadXml($"{comment.Text}"); + + return LNode.Trivia(Symbol.For("DocComment"), xmlDocument); + } + + public static bool TryParse(Parser parser, out LNode node) + { + var result = parser.Iterator.IsMatch(TokenType.DocComment); + + node = result ? Parse(parser) : LNode.Missing; + + return result; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/DefaultExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/DefaultExpression.cs new file mode 100644 index 0000000..61e184d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/DefaultExpression.cs @@ -0,0 +1,22 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class DefaultExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + //default(i32) + //default + if (iterator.ConsumeIfMatch(TokenType.OpenParen)) + { + var type = TypeLiteral.Parse(iterator, parser); + + iterator.Match(TokenType.CloseParen); + + return SyntaxTree.Default(type); + } + + return SyntaxTree.Default(); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/GroupExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/GroupExpression.cs new file mode 100644 index 0000000..b55f8e5 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/GroupExpression.cs @@ -0,0 +1,18 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class GroupOrTupleExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var exprs = Expression.ParseList(parser, TokenType.CloseParen); + + if (exprs.Count == 1) + { + return SyntaxTree.Factory.InParens(exprs[0]); + } + + return SyntaxTree.Factory.Tuple(exprs); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/InitializerListExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/InitializerListExpression.cs new file mode 100644 index 0000000..72e5f5d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/InitializerListExpression.cs @@ -0,0 +1,30 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class InitializerListExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var elements = new LNodeList(); + + do + { + if (iterator.Current.Type == TokenType.CloseSquare) + { + break; + } + + elements.Add(Expression.Parse(parser)); + + if (iterator.Current.Type != TokenType.CloseSquare) + { + iterator.Match(TokenType.Comma); + } + } while (iterator.Current.Type != TokenType.CloseSquare); + + iterator.Match(TokenType.CloseSquare); + + return SyntaxTree.ArrayInstantiation(elements); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchExpression.cs new file mode 100644 index 0000000..3373de2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchExpression.cs @@ -0,0 +1,36 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions.Match; + +public sealed class MatchExpression : IParsePoint +{ + /* + * match a with + 12 => 13, + i32 num => num + 2, + _ => 0 + 4; + */ + + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var matchArgument = Expression.Parse(parser); + + iterator.Match(TokenType.With); + + var conditions = new LNodeList(); + + while (iterator.Current.Type != TokenType.Semicolon) + { + conditions.Add(MatchRule.Parse(iterator, parser)); + + if (iterator.Current.Type == TokenType.Semicolon) + { + break; + } + + iterator.Match(TokenType.Comma); + } + + return SyntaxTree.Factory.Call(LNode.Id(Symbols.Match), matchArgument).WithAttrs(conditions); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchRule.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchRule.cs new file mode 100644 index 0000000..0333c9d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/Match/MatchRule.cs @@ -0,0 +1,72 @@ +using Loyc; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions.Match; + +public sealed class MatchRule +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + if (iterator.Current.Type == TokenType.Underscore) // _ => 0 + { + iterator.NextToken(); + + iterator.Match(TokenType.GoesTo); + + var result = Expression.Parse(parser); + + return SyntaxTree.Factory.Tuple(LNode.Literal((Symbol)"_"), result); + } + + if (iterator.Peek(1).Type == TokenType.GoesTo) //12 => 13 + { + var matcher = Expression.Parse(parser); + + iterator.Match(TokenType.GoesTo); + + var result = Expression.Parse(parser); + + return SyntaxTree.Factory.Tuple(matcher, result); + } + + if (iterator.Current.IsOperator()) // > 12 => false + { + var operatorToken = iterator.Current; + iterator.NextToken(); + + var condition = Expression.Parse(parser); + + iterator.Match(TokenType.GoesTo); + + var result = Expression.Parse(parser); + + return SyntaxTree.Factory.Tuple(SyntaxTree.Unary((Symbol)operatorToken.Text, condition), result); + } + + if (iterator.Current.Type == TokenType.Identifier && + iterator.Peek(1).Type == TokenType.Identifier) //i32 num => num + 2 + { + var type = TypeLiteral.Parse(iterator, parser); + var name = iterator.NextToken().Text; + + iterator.Match(TokenType.GoesTo); + + var result = Expression.Parse(parser); + + return SyntaxTree.Factory.Tuple(SyntaxTree.Factory.Var(type, name), result); + } + + if (iterator.Current.Type == TokenType.Identifier) //i32 => 32 + { + var type = TypeLiteral.Parse(iterator, parser); + + iterator.Match(TokenType.GoesTo); + + var result = Expression.Parse(parser); + + return SyntaxTree.Factory.Tuple(type, result); + } + + return LNode.Missing; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NameExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NameExpression.cs new file mode 100644 index 0000000..002c0e8 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NameExpression.cs @@ -0,0 +1,31 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class NameExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var nameToken = iterator.Peek(-1); + var nameExpression = SyntaxTree.Factory.Id(nameToken.Text); + + if (iterator.Current.Type == TokenType.OpenSquare) + { + iterator.NextToken(); + + return SyntaxTree.ArrayInstantiation(nameExpression, Expression.ParseList(parser, TokenType.CloseSquare)) + .WithRange(nameToken, iterator.Prev); + } + + if (iterator.Current.Type == TokenType.OpenParen) + { + iterator.NextToken(); + + var arguments = Expression.ParseList(parser, TokenType.CloseParen); + + return SyntaxTree.Factory.Call(nameExpression, arguments).WithRange(nameToken, iterator.Prev); + } + + return nameExpression.WithRange(nameToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NoneExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NoneExpression.cs new file mode 100644 index 0000000..8ae60c0 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/NoneExpression.cs @@ -0,0 +1,11 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class NoneExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + return SyntaxTree.None(); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/SizeOfExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/SizeOfExpression.cs new file mode 100644 index 0000000..3e6b08d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/SizeOfExpression.cs @@ -0,0 +1,19 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class SizeOfExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + //sizeof(i32) + + iterator.Match(TokenType.OpenParen); + + var type = TypeLiteral.Parse(iterator, parser); + + iterator.Match(TokenType.CloseParen); + + return SyntaxTree.SizeOf(type); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/TypeofExpression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/TypeofExpression.cs new file mode 100644 index 0000000..7c03c22 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Expressions/TypeofExpression.cs @@ -0,0 +1,17 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Expressions; + +public sealed class TypeofExpression : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + iterator.Match(TokenType.OpenParen); + + var type = TypeLiteral.Parse(iterator, parser); + + iterator.Match(TokenType.CloseParen); + + return SyntaxTree.TypeOfExpression(type); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Modifier.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Modifier.cs new file mode 100644 index 0000000..297cecb --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Modifier.cs @@ -0,0 +1,54 @@ +using Backlang.Codeanalysis.Core; +using Loyc; +using Loyc.Syntax; +using System.Collections.Immutable; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public sealed class Modifier +{ + private static readonly ImmutableDictionary _possibleModifiers = + new Dictionary + { + { TokenType.Static, CodeSymbols.Static }, + { TokenType.Public, CodeSymbols.Public }, + { TokenType.Protected, CodeSymbols.Protected }, + { TokenType.Private, CodeSymbols.Private }, + { TokenType.Internal, CodeSymbols.Internal }, + { TokenType.Operator, CodeSymbols.Operator }, + { TokenType.Abstract, CodeSymbols.Abstract }, + { TokenType.Override, CodeSymbols.Override }, + { TokenType.Extern, CodeSymbols.Extern } + }.ToImmutableDictionary(); + + public static bool TryParse(Parser parser, out LNodeList node) + { + var modifiers = new LNodeList(); + + while (_possibleModifiers.ContainsKey(parser.Iterator.Current.Type)) + { + var modifier = ParseSingle(parser.Iterator); + if (modifiers.Contains(modifier)) + { + parser.AddError(new LocalizableString(ErrorID.DuplicateModifier, modifier.Name.Name), modifier.Range); + + continue; + } + + modifiers.Add(modifier); + } + + node = modifiers; + + return modifiers.Count > 0; + } + + private static LNode ParseSingle(TokenIterator iterator) + { + var currentToken = iterator.Current; + var mod = SyntaxTree.Factory.Id(_possibleModifiers[currentToken.Type]); + iterator.NextToken(); + + return mod.WithRange(currentToken); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Signature.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Signature.cs new file mode 100644 index 0000000..87a03ed --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Signature.cs @@ -0,0 +1,54 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Parsing.AST.Declarations; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public sealed class Signature +{ + public static LNode Parse(Parser parser) + { + var iterator = parser.Iterator; + + if (!TypeLiteral.TryParse(parser, out var name)) + { + var range = new SourceRange(parser.Document, iterator.Current.Start, iterator.Current.Text.Length); + + parser.AddError(new LocalizableString(ErrorID.ExpectedTypeLiteral, iterator.Current.Text), range); + } + + LNode returnType = LNode.Missing; + iterator.Match(TokenType.OpenParen); + + var parameters = ParameterDeclaration.ParseList(parser); + + LNodeList generics = new(); + while (iterator.IsMatch(TokenType.Where)) + { + iterator.NextToken(); + var genericName = LNode.Id(iterator.Match(TokenType.Identifier).Text); + iterator.Match(TokenType.Colon); + var bases = new LNodeList(); + do + { + if (iterator.IsMatch(TokenType.Comma)) + { + iterator.NextToken(); + } + + bases.Add(TypeLiteral.Parse(iterator, parser)); + } while (iterator.IsMatch(TokenType.Comma)); + + generics.Add(LNode.Call(Symbols.Where, LNode.List(genericName, LNode.Call(CodeSymbols.Base, bases)))); + } + + if (iterator.IsMatch(TokenType.Arrow)) + { + iterator.NextToken(); + + returnType = TypeLiteral.Parse(iterator, parser); + } + + return SyntaxTree.Signature(name, returnType, parameters, generics); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/BreakStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/BreakStatement.cs new file mode 100644 index 0000000..c749506 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/BreakStatement.cs @@ -0,0 +1,14 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class BreakStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + iterator.Match(TokenType.Semicolon); + + return LNode.Call(CodeSymbols.Break).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ExpressionStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ExpressionStatement.cs new file mode 100644 index 0000000..9518ade --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ExpressionStatement.cs @@ -0,0 +1,15 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class ExpressionStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var expr = Expression.Parse(parser); + + iterator.Match(TokenType.Semicolon); + + return expr.WithRange(expr.Range.StartIndex, iterator.Prev.End); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/IfStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/IfStatement.cs new file mode 100644 index 0000000..af0ab55 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/IfStatement.cs @@ -0,0 +1,24 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class IfStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + // if cond {} else {} + var keywordToken = iterator.Prev; + var cond = Expression.Parse(parser); + var body = Statement.ParseOneOrBlock(parser); + LNode elseBlock = LNode.Missing; + + if (iterator.Current.Type == TokenType.Else) + { + iterator.NextToken(); + + elseBlock = Statement.ParseOneOrBlock(parser); + } + + return SyntaxTree.If(cond, body, elseBlock).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ImportStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ImportStatement.cs new file mode 100644 index 0000000..b6acdd3 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ImportStatement.cs @@ -0,0 +1,18 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class ImportDeclaration : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + //import + //import . + var keywordToken = iterator.Prev; + var tree = SyntaxTree.Import(Expression.Parse(parser)); + + iterator.Match(TokenType.Semicolon); + + return tree.WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ContinueStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ContinueStatement.cs new file mode 100644 index 0000000..02bff3b --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ContinueStatement.cs @@ -0,0 +1,14 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements.Loops; + +public sealed class ContinueStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + iterator.Match(TokenType.Semicolon); + + return LNode.Call(CodeSymbols.Continue).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/DoWhileStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/DoWhileStatement.cs new file mode 100644 index 0000000..394b907 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/DoWhileStatement.cs @@ -0,0 +1,21 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements.Loops; + +public sealed class DoWhileStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + var body = Statement.ParseBlock(parser); + + iterator.Match(TokenType.While); + + var cond = Expression.Parse(parser); + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.DoWhile(body, cond).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ForStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ForStatement.cs new file mode 100644 index 0000000..5a246b2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/ForStatement.cs @@ -0,0 +1,31 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements.Loops; + +public sealed class ForStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + //for x : i32 in 1..12 + //for x in arr + var keywordToken = iterator.Prev; + var varExpr = Expression.Parse(parser); + + LNode type = LNode.Missing; + + if (iterator.Current.Type == TokenType.Colon) + { + iterator.NextToken(); + + type = TypeLiteral.Parse(iterator, parser); + } + + iterator.Match(TokenType.In); + + var collExpr = Expression.Parse(parser); + var body = Statement.ParseOneOrBlock(parser); + + return SyntaxTree.For(SyntaxTree.Factory.Tuple(varExpr, type), collExpr, body) + .WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/WhileStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/WhileStatement.cs new file mode 100644 index 0000000..af52d52 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Loops/WhileStatement.cs @@ -0,0 +1,16 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements.Loops; + +public sealed class WhileStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + var cond = Expression.Parse(parser); + var body = Statement.ParseOneOrBlock(parser); + + return SyntaxTree.While(cond, body).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/MacroBlockStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/MacroBlockStatement.cs new file mode 100644 index 0000000..1c731e8 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/MacroBlockStatement.cs @@ -0,0 +1,48 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class MacroBlockStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var nameToken = iterator.Prev; + + var currPos = iterator.Position - 1; + + var nameExpression = LNode.Id(nameToken.Text); + + if (iterator.ConsumeIfMatch(TokenType.OpenParen)) + { + var arguments = Expression.ParseList(parser, TokenType.CloseParen); + + if (iterator.Current.Type == TokenType.OpenCurly) + { + //custom code block with arguments + var body = Statement.ParseBlock(parser); + arguments = arguments.Add(body); + + return SyntaxTree.Factory.Call(nameExpression, arguments).SetStyle(NodeStyle.StatementBlock) + .WithRange(nameToken, iterator.Prev); + } + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.Factory.Call(nameExpression, arguments).WithRange(nameToken, iterator.Prev); + } + + if (iterator.Current.Type == TokenType.OpenCurly) + { + //custom code block without arguments + var body = Statement.ParseBlock(parser); + var arguments = LNode.List(LNode.Missing, body); + + return SyntaxTree.Factory.Call(nameExpression, arguments).SetStyle(NodeStyle.StatementBlock) + .WithRange(nameToken, iterator.Prev); + } + + iterator.Position = currPos; + + return ExpressionStatement.Parse(iterator, parser); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ReturnStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ReturnStatement.cs new file mode 100644 index 0000000..190afd8 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ReturnStatement.cs @@ -0,0 +1,21 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class ReturnStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var arguments = LNode.List(); + + if (!iterator.IsMatch(TokenType.Semicolon)) + { + arguments.Add(Expression.Parse(parser)); + } + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.Factory.Call(CodeSymbols.Return, arguments).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Statement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Statement.cs new file mode 100644 index 0000000..9ca84a7 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/Statement.cs @@ -0,0 +1,34 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public static class Statement +{ + public static LNode ParseBlock(Parser parser) + { + var openCurlyToken = parser.Iterator.Match(TokenType.OpenCurly); + + var body = new List(); + while (!parser.Iterator.IsMatch(TokenType.CloseCurly) && !parser.Iterator.IsMatch(TokenType.EOF)) + { + body.Add(parser.InvokeStatementParsePoint()); + } + + parser.Iterator.Match(TokenType.CloseCurly); + + return SyntaxTree.Factory.Braces(body).WithStyle(NodeStyle.StatementBlock) + .WithRange(openCurlyToken, parser.Iterator.Prev); + } + + public static LNode ParseOneOrBlock(Parser parser) + { + if (parser.Iterator.IsMatch(TokenType.OpenCurly)) + { + return ParseBlock(parser); + } + + var node = parser.InvokeStatementParsePoint(); + + return SyntaxTree.Factory.Braces(node).WithStyle(NodeStyle.StatementBlock).WithRange(node.Range); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/SwitchStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/SwitchStatement.cs new file mode 100644 index 0000000..1d61634 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/SwitchStatement.cs @@ -0,0 +1,167 @@ +using Backlang.Codeanalysis.Core; +using Loyc; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class SwitchStatement : IParsePoint +{ + /* + * switch element { + * case cond: oneExpr; + * case cond: { block; } + * if boolean: oneExpr; + * if boolean: { block; } + * break when > value: { block; } + * default: oneExpr; + * default: { block; } + * } + */ + + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var element = Expression.Parse(parser); + + parser.Iterator.Match(TokenType.OpenCurly); + + var cases = new LNodeList(); + + while (!parser.Iterator.IsMatch(TokenType.CloseCurly)) + { + var autoBreak = iterator.IsMatch(TokenType.Break); + + if (autoBreak) + { + iterator.Match(TokenType.Break); + } + + if (iterator.IsMatch(TokenType.Case)) + { + cases.Add(ParseCase(parser, autoBreak)); + } + else if (iterator.IsMatch(TokenType.If)) + { + cases.Add(ParseIf(parser, autoBreak)); + } + else if (iterator.IsMatch(TokenType.When)) + { + cases.Add(ParseWhen(parser, autoBreak)); + } + else if (iterator.IsMatch(TokenType.Default)) + { + cases.Add(ParseDefault(parser, autoBreak)); + } + else + { + var range = new SourceRange(parser.Document, iterator.Current.Start, iterator.Current.Text.Length); + + parser.AddError(new LocalizableString(ErrorID.UnknownSwitchOption), range); + return LNode.Missing; + } + } + + parser.Iterator.Match(TokenType.CloseCurly); + + return SyntaxTree.Switch(element, cases).WithRange(keywordToken, iterator.Prev); + } + + private static LNode ParseCase(Parser parser, bool autoBreak) + { + var keywordToken = parser.Iterator.Match(TokenType.Case); + + var condition = Expression.Parse(parser); + + parser.Iterator.Match(TokenType.Colon); + + var body = Statement.ParseOneOrBlock(parser); + + if (autoBreak) + { + body = body.PlusArg(LNode.Call(CodeSymbols.Break)); + } + + return SyntaxTree.Case(condition, body).WithRange(keywordToken, parser.Iterator.Prev); + } + + private static LNode ParseDefault(Parser parser, bool autoBreak) + { + parser.Iterator.Match(TokenType.Default); + + parser.Iterator.Match(TokenType.Colon); + + var body = Statement.ParseOneOrBlock(parser); + + if (autoBreak) + { + body = body.PlusArg(LNode.Call(CodeSymbols.Break)); + } + + return SyntaxTree.Case(LNode.Call(CodeSymbols.Default), body); + } + + private static LNode ParseIf(Parser parser, bool autoBreak) + { + parser.Iterator.Match(TokenType.If); + + var condition = Expression.Parse(parser); + + parser.Iterator.Match(TokenType.Colon); + + var body = Statement.ParseOneOrBlock(parser); + + if (autoBreak) + { + body = body.PlusArg(LNode.Call(CodeSymbols.Break)); + } + + return SyntaxTree.If(condition, body, SyntaxTree.Factory.Braces()); + } + + private static LNode ParseWhen(Parser parser, bool autoBreak) + { + parser.Iterator.Match(TokenType.When); + + LNode binOp = LNode.Missing; + LNode right; + if (Expression.GetBinaryOperatorPrecedence(parser.Iterator.Current.Type) > 0) + { + // with binary expression + var operatorToken = parser.Iterator.NextToken(); + + right = Expression.Parse(parser); + binOp = LNode.Call(GSymbol.Get($"'{operatorToken.Text}")); + } + else + { + // with element function + if (!parser.Iterator.IsMatch(TokenType.Identifier)) + { + var range = new SourceRange(parser.Document, parser.Iterator.Current.Start, + parser.Iterator.Current.Text.Length); + + parser.AddError(new LocalizableString(ErrorID.ExpectedIdentifier, parser.Iterator.Current.Text), range); + + return LNode.Missing; + } + + var name = LNode.Id(parser.Iterator.Current.Text); + parser.Iterator.Match(TokenType.Identifier); + parser.Iterator.Match(TokenType.OpenParen); + var args = Expression.ParseList(parser, TokenType.CloseParen); + + right = LNode.Call(name, args); + } + + parser.Iterator.Match(TokenType.Colon); + + var body = Statement.ParseOneOrBlock(parser); + + if (autoBreak) + { + body = body.PlusArg(LNode.Call(CodeSymbols.Break)); + } + + return SyntaxTree.When(binOp, right, body); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ThrowStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ThrowStatement.cs new file mode 100644 index 0000000..de49bfb --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/ThrowStatement.cs @@ -0,0 +1,21 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public class ThrowStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + LNode arg = LNode.Missing; + if (!iterator.IsMatch(TokenType.Semicolon)) + { + arg = Expression.Parse(parser); + } + + iterator.Match(TokenType.Semicolon); + + return SyntaxTree.Throw(arg).WithRange(keywordToken, iterator.Prev); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/TryStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/TryStatement.cs new file mode 100644 index 0000000..b56f6df --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/TryStatement.cs @@ -0,0 +1,51 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public sealed class TryStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + var body = Statement.ParseOneOrBlock(parser); + LNodeList catches = new(LNode.Missing); + + if (iterator.Current.Type != TokenType.Catch) + { + var range = new SourceRange(parser.Document, iterator.Current.Start, iterator.Current.Text.Length); + + parser.AddError(new LocalizableString(ErrorID.NoCatchBlock), range); + } + + while (iterator.Current.Type == TokenType.Catch) + { + iterator.NextToken(); + + catches.Add(ParseCatch(parser)); + } + + LNode finallly = LNode.Missing; + if (iterator.IsMatch(TokenType.Finally)) + { + iterator.Match(TokenType.Finally); + finallly = Statement.ParseOneOrBlock(parser); + } + + return SyntaxTree.Try(body, SyntaxTree.Factory.AltList(catches), finallly) + .WithRange(keywordToken, iterator.Prev); + } + + private static LNode ParseCatch(Parser parser) + { + parser.Iterator.Match(TokenType.OpenParen); + var exceptionValueName = LNode.Id(parser.Iterator.Match(TokenType.Identifier).Text); + parser.Iterator.Match(TokenType.Colon); + var exceptionType = LNode.Id(parser.Iterator.Match(TokenType.Identifier).Text); + parser.Iterator.Match(TokenType.CloseParen); + + var body = Statement.ParseOneOrBlock(parser); + + return SyntaxTree.Catch(exceptionType, exceptionValueName, body); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/VariableStatement.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/VariableStatement.cs new file mode 100644 index 0000000..fbafac4 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Statements/VariableStatement.cs @@ -0,0 +1,46 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST.Statements; + +public class VariableStatement : IParsePoint +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + var keywordToken = iterator.Prev; + + var isMutable = false; + var type = SyntaxTree.Type("", LNode.List()); + LNode value = LNode.Missing; + + Token mutableToken = null; + + if (iterator.Current.Type == TokenType.Mutable) + { + isMutable = true; + mutableToken = iterator.NextToken(); + } + + var nameToken = iterator.Match(TokenType.Identifier); + var name = SyntaxTree.Factory.Id(nameToken.Text).WithRange(nameToken); + + if (iterator.Current.Type == TokenType.Colon) + { + iterator.NextToken(); + + type = TypeLiteral.Parse(iterator, parser); + } + + if (iterator.Current.Type == TokenType.EqualsToken) + { + iterator.NextToken(); + + value = Expression.Parse(parser); + } + + iterator.Match(TokenType.Semicolon); + + var node = SyntaxTree.Factory.Var(type, name, value).WithRange(keywordToken, iterator.Prev); + + return isMutable ? node.WithAttrs(SyntaxTree.Factory.Id(Symbols.Mutable).WithRange(mutableToken)) : node; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/Symbols.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Symbols.cs new file mode 100644 index 0000000..d64a70b --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/Symbols.cs @@ -0,0 +1,35 @@ +using Loyc; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public static class Symbols +{ + public static readonly Symbol Annotation = GSymbol.Get("#annotation"); + public static readonly Symbol Bitfield = GSymbol.Get("#bitfield"); + public static readonly Symbol ColonColon = GSymbol.Get("'::"); + public static readonly Symbol Constructor = GSymbol.Get("#constructor"); + public static readonly Symbol Destructor = GSymbol.Get("#destructor"); + public static readonly Symbol DiscriminatedType = GSymbol.Get("#discrimType"); + public static readonly Symbol DiscriminatedUnion = GSymbol.Get("#discrimUnion"); + public static readonly Symbol Float16 = GSymbol.Get("#float16"); + public static readonly Symbol Float32 = GSymbol.Get("#float32"); + public static readonly Symbol Float64 = GSymbol.Get("#float64"); + public static readonly Symbol Global = GSymbol.Get("#global"); + public static readonly Symbol Implementation = GSymbol.Get("#implement"); + public static readonly Symbol Inheritance = GSymbol.Get("#inheritance"); + public static readonly Symbol Macro = GSymbol.Get("#macro"); + public static readonly Symbol Match = GSymbol.Get("#match"); + public static readonly Symbol Mutable = GSymbol.Get("#mutable"); + public static readonly Symbol PointerType = GSymbol.Get("#type*"); + public static readonly Symbol RefType = GSymbol.Get("#type&"); + public static readonly Symbol NullableType = GSymbol.Get("#type?"); + public static readonly Symbol Range = GSymbol.Get("'.."); + public static readonly Symbol ToExpand = GSymbol.Get("'to_expand'"); + public static readonly Symbol TypeLiteral = GSymbol.Get("#type"); + public static readonly Symbol Union = GSymbol.Get("#union"); + public static readonly Symbol Where = GSymbol.Get("#where"); + public static readonly Symbol Init = GSymbol.Get("#init"); + public static readonly Symbol Unit = GSymbol.Get("#unit"); + public static readonly Symbol UnitDecl = GSymbol.Get("#unitDecl"); + public static readonly Symbol AssertNonNull = GSymbol.Get("#notnull"); +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/AST/TypeLiteral.cs b/NewSource/Backlang.CodeAnalysis/Parsing/AST/TypeLiteral.cs new file mode 100644 index 0000000..8c1ba12 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/AST/TypeLiteral.cs @@ -0,0 +1,162 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing.AST; + +public sealed class TypeLiteral +{ + public static LNode Parse(TokenIterator iterator, Parser parser) + { + LNode typeNode; + var typeToken = iterator.Current; + + if (iterator.IsMatch(TokenType.Identifier)) + { + var typename = iterator.Match(TokenType.Identifier).Text; + var args = new LNodeList(); + + typeNode = SyntaxTree.Type(typename, new LNodeList()).WithRange(typeToken); + + if (iterator.IsMatch(TokenType.Star)) + { + iterator.NextToken(); + + typeNode = SyntaxTree.Pointer(typeNode).WithRange(typeToken, iterator.Prev); + } + + if (iterator.IsMatch(TokenType.Ampersand)) + { + iterator.NextToken(); + + typeNode = SyntaxTree.RefType(typeNode).WithRange(typeToken, iterator.Prev); + } + else if (iterator.IsMatch(TokenType.Questionmark)) + { + iterator.NextToken(); + + typeNode = SyntaxTree.NullableType(typeNode).WithRange(typeToken, iterator.Prev); + } + else if (iterator.IsMatch(TokenType.OpenSquare)) + { + typeNode = ParseArrayType(iterator, typeNode, typeToken); + } + else if (iterator.IsMatch(TokenType.LessThan)) + { + typeNode = ParseGenericType(iterator, parser, typeToken, typename, args); + } + } + else if (iterator.IsMatch(TokenType.None)) + { + typeNode = SyntaxTree.Type("none", LNode.List()).WithRange(typeToken); + iterator.NextToken(); + } + else if (iterator.IsMatch(TokenType.OpenParen)) + { + typeNode = ParseFunctionOrTupleType(iterator, parser, typeToken); + } + else + { + parser.AddError(new LocalizableString(ErrorID.UnexpecedType, + TokenIterator.GetTokenRepresentation(iterator.Current.Type))); //ToDo: Add Range + + typeNode = LNode.Missing; + iterator.NextToken(); + } + + return typeNode; + } + + public static bool TryParse(Parser parser, out LNode node) + { + var cursor = parser.Iterator.Position; + node = Parse(parser.Iterator, parser); + + if (node == LNode.Missing) + { + parser.Iterator.Position = cursor; + return false; + } + + return true; + } + + private static LNode ParseFunctionOrTupleType(TokenIterator iterator, Parser parser, Token typeToken) + { + LNode typeNode; + iterator.Match(TokenType.OpenParen); + + var parameters = new LNodeList(); + while (parser.Iterator.Current.Type != TokenType.CloseParen) + { + parameters.Add(Parse(iterator, parser)); + + if (parser.Iterator.Current.Type != TokenType.CloseParen) + { + parser.Iterator.Match(TokenType.Comma); + } + } + + parser.Iterator.Match(TokenType.CloseParen); + + if (iterator.Current.Type == TokenType.Arrow) + { + iterator.NextToken(); + + var returnType = Parse(iterator, parser); + + typeNode = SyntaxTree.Factory.Call(CodeSymbols.Fn, + LNode.List(returnType, LNode.Missing, LNode.Call(CodeSymbols.AltList, parameters))) + .WithRange(typeToken, iterator.Prev); + } + else + { + typeNode = SyntaxTree.Factory.Tuple(parameters).WithRange(typeToken, iterator.Prev); + } + + return typeNode; + } + + private static LNode ParseGenericType(TokenIterator iterator, Parser parser, Token typeToken, string typename, + LNodeList args) + { + LNode typeNode; + iterator.NextToken(); + + while (!iterator.IsMatch(TokenType.GreaterThan)) + { + if (iterator.IsMatch(TokenType.Identifier)) + { + args.Add(Parse(iterator, parser)); + } + + if (!iterator.IsMatch(TokenType.GreaterThan)) + { + iterator.Match(TokenType.Comma); + } + } + + iterator.Match(TokenType.GreaterThan); + + typeNode = SyntaxTree.Type(typename, args).WithRange(typeToken, parser.Iterator.Prev); + return typeNode; + } + + private static LNode ParseArrayType(TokenIterator iterator, LNode typeNode, Token typeToken) + { + iterator.NextToken(); + + var dimensions = 1; + + while (iterator.IsMatch(TokenType.Comma)) + { + dimensions++; + + iterator.NextToken(); + } + + iterator.Match(TokenType.CloseSquare); + + typeNode = SyntaxTree.Array(typeNode, dimensions).WithRange(typeToken, iterator.Prev); + return typeNode; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Expression.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Expression.cs new file mode 100644 index 0000000..3be40ef --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Expression.cs @@ -0,0 +1,153 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Core.Attributes; +using Loyc; +using Loyc.Syntax; +using System.Reflection; + +namespace Backlang.Codeanalysis.Parsing; + +public static class Expression +{ + public static readonly Dictionary BinaryOperators = new(); + public static readonly Dictionary PostUnaryOperators = new(); + public static readonly Dictionary PreUnaryOperators = new(); + + static Expression() + { + var typeValues = (TokenType[])Enum.GetValues(typeof(TokenType)); + + foreach (var op in typeValues) + { + var attributes = op.GetType().GetField(Enum.GetName(op)).GetCustomAttributes(true); + + if (attributes != null && attributes.Any()) + { + foreach (var attribute in attributes) + { + if (attribute.IsUnary) + { + if (attribute.IsPostUnary) + { + PostUnaryOperators.Add(op, attribute.Precedence); + } + else + { + PreUnaryOperators.Add(op, attribute.Precedence); + } + } + else + { + BinaryOperators.Add(op, attribute.Precedence); + } + } + } + } + } + + public static int GetBinaryOperatorPrecedence(TokenType kind) + { + return BinaryOperators.GetValueOrDefault(kind); + } + + public static LNode Parse(Parser parser, ParsePoints parsePoints = null, int parentPrecedence = 0) + { + LNode left = null; + var preUnaryOperatorPrecedence = GetPreUnaryOperatorPrecedence(parser.Iterator.Current.Type); + + if (preUnaryOperatorPrecedence != 0 && preUnaryOperatorPrecedence >= parentPrecedence) + { + if (IsPreUnary(parser.Iterator.Current.Type)) + { + var operatorToken = parser.Iterator.NextToken(); + + var operand = Parse(parser, parsePoints, preUnaryOperatorPrecedence + 1); + + left = SyntaxTree.Unary(GSymbol.Get($"'{operatorToken.Text}"), operand) + .WithRange(operatorToken.Start, operand.Range.EndIndex).WithStyle(NodeStyle.PrefixNotation); + } + } + else + { + left = parser.ParsePrimary(); + + //parsing postunarys for: hello?; + var postUnaryOperatorPrecedence = GetPostUnaryOperatorPrecedence(parser.Iterator.Current.Type); + + if (postUnaryOperatorPrecedence != 0 && postUnaryOperatorPrecedence >= parentPrecedence) + { + if (IsPostUnary(parser.Iterator.Current.Type)) + { + var unaryOperatorToken = parser.Iterator.NextToken(); + + left = SyntaxTree.Unary(GSymbol.Get($"'suf{unaryOperatorToken.Text}"), left) + .WithRange(left.Range.StartIndex, unaryOperatorToken.End).WithStyle(NodeStyle.Operator); + } + } + } + + while (true) + { + var precedence = GetBinaryOperatorPrecedence(parser.Iterator.Current.Type); + if (precedence == 0 || precedence <= parentPrecedence) + { + break; + } + + var operatorToken = parser.Iterator.NextToken(); + var right = Parse(parser, parsePoints, precedence); + + left = SyntaxTree.Binary(GSymbol.Get($"'{operatorToken.Text}"), left, right) + .WithRange(left.Range.StartIndex, right.Range.StartIndex); + + // parsing postunary for: Hello::new()? = false; + var postUnaryOperatorPrecedence = GetPostUnaryOperatorPrecedence(parser.Iterator.Current.Type); + + if (postUnaryOperatorPrecedence != 0 && postUnaryOperatorPrecedence >= parentPrecedence) + { + if (IsPostUnary(parser.Iterator.Current.Type)) + { + var unaryOperatorToken = parser.Iterator.NextToken(); + + left = SyntaxTree.Unary(GSymbol.Get($"'suf{unaryOperatorToken.Text}"), left) + .WithRange(left.Range.StartIndex, unaryOperatorToken.End).WithStyle(NodeStyle.Operator); + } + } + } + + return left; + } + + public static LNodeList ParseList(Parser parser, TokenType terminator, bool consumeTerminator = true) + { + return ParsingHelpers.ParseSeperated(parser, terminator, + consumeTerminator: consumeTerminator); + } + + private static int GetPreUnaryOperatorPrecedence(TokenType kind) + { + return PreUnaryOperators.GetValueOrDefault(kind); + } + + private static int GetPostUnaryOperatorPrecedence(TokenType kind) + { + return PostUnaryOperators.GetValueOrDefault(kind); + } + + private static bool IsPreUnary(TokenType kind) + { + return PreUnaryOperators.ContainsKey(kind); + } + + private static bool IsPostUnary(TokenType kind) + { + return PostUnaryOperators.ContainsKey(kind); + } + + private class ExpressionParser : IParsePoint + { + public static LNode Parse(TokenIterator iterator, Parser parser) + { + return Expression.Parse(parser); + } + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/IParsePoint.cs b/NewSource/Backlang.CodeAnalysis/Parsing/IParsePoint.cs new file mode 100644 index 0000000..a36d7c8 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/IParsePoint.cs @@ -0,0 +1,8 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public interface IParsePoint +{ + static abstract LNode Parse(TokenIterator iterator, Parser parser); +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/LNodeExtensions.cs b/NewSource/Backlang.CodeAnalysis/Parsing/LNodeExtensions.cs new file mode 100644 index 0000000..12ebacd --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/LNodeExtensions.cs @@ -0,0 +1,33 @@ +using Backlang.Codeanalysis.Parsing.AST; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public static class LNodeExtensions +{ + public static LNode WithRange(this LNode node, int start, int end) + { + return node.WithRange(new SourceRange(node.Source, start, Math.Abs(start - end))).WithAttrs(node.Attrs); + } + + public static LNode WithRange(this LNode node, Token token) + { + return WithRange(node, token.Start, token.End); + } + + public static LNode WithRange(this LNode node, Token startToken, Token endtoken) + { + return WithRange(node, startToken.Start, endtoken.End); + } + + public static LNode FromToken(this LNodeFactory factory, Token token) + { + return factory.Id(token.Text).WithRange(token); + } + + public static bool IsNoneType(this LNode node) + { + return node.Name == Symbols.TypeLiteral && node.Args[0].Args[0].Name.Name == "none" && + node.Args[0].Args[0].IsId; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Lexer.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Lexer.cs new file mode 100644 index 0000000..34ef246 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Lexer.cs @@ -0,0 +1,416 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Core.Attributes; +using Loyc.Syntax; +using System.Reflection; +using System.Text; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed class Lexer : BaseLexer +{ + private static readonly Dictionary _symbolTokens = new(StringComparer.Ordinal); + + static Lexer() + { + var typeValues = (TokenType[])Enum.GetValues(typeof(TokenType)); + + foreach (var op in typeValues) + { + var attributes = op.GetType() + .GetField(Enum.GetName(op)).GetCustomAttributes(true); + + if (attributes != null && attributes.Any()) + { + foreach (var attribute in attributes) + { + _symbolTokens.Add(attribute.Lexeme, op); + } + } + } + + _symbolTokens = new Dictionary(_symbolTokens.OrderByDescending(_ => _.Key.Length)); + } + + protected override Token NextToken() + { + if (IsMatch("///")) + { + return LexDocComment(); + } + + SkipWhitespaces(); + SkipComments(); + + if (_position >= _document.Text.Count) + { + return new Token(TokenType.EOF, "\0", _position, _position, _line, _column); + } + + if (Current() == '\'') + { + return LexCharLiteral(); + } + + if (Current() == '"') + { + return LexDoubleQuoteString(); + } + + if (IsMatch("0x")) + { + return LexHexNumber(); + } + + if (IsMatch("0b")) + { + return LexBinaryNumber(); + } + + if (char.IsDigit(Current())) + { + return LexDecimalNumber(); + } + + if (IsIdentifierStartDigit()) + { + var identifier = LexIdentifier(); + + if (IsOperatorIdentifier(identifier)) + { + identifier.Type = GetOperatorKind(identifier); + } + + return identifier; + } + + foreach (var symbol in _symbolTokens) + { + if (IsMatch(symbol.Key)) + { + return LexSymbol(symbol); + } + } + + ReportError(); + + return Token.Invalid; + } + + private Token LexDocComment() + { + var oldPos = _position; + var contentBuilder = new StringBuilder(); + + do + { + contentBuilder.AppendLine(ReadLine().TrimStart('/').Trim()); + } while (IsMatch("///")); + + return new Token(TokenType.DocComment, contentBuilder.ToString(), oldPos, _position, _line, _column); + } + + + private string ReadLine() + { + var sb = new StringBuilder(); + + while (Current() != '\n') + { + Advance(); + _column++; + } + + Advance(); + _column = 0; + _line++; + + return sb.ToString(); + } + + private static bool IsBinaryDigit(char c) + { + return c == '0' || c == '1'; + } + + private static bool IsHex(char c) + { + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); + } + + private TokenType GetOperatorKind(Token identifier) + { + foreach (var s in _symbolTokens) + { + if (identifier.Text == s.Key) + { + return s.Value; + } + } + + return TokenType.Identifier; + } + + private bool IsIdentifierDigit() + { + return char.IsLetterOrDigit(Current()) || Current() == '_'; + } + + private bool IsIdentifierStartDigit() + { + return char.IsLetter(Current()) || Current() == '_'; + } + + private bool IsMatch(string token) + { + var result = Current() == token[0]; + + for (var i = 1; i < token.Length; i++) + { + if (result) + { + result = result && Peek(i) == token[i]; + } + } + + return result; + } + + private bool IsOperatorIdentifier(Token identifier) + { + return _symbolTokens.ContainsKey(identifier.Text); + } + + private Token LexBinaryNumber() + { + _position += 2; + _column += 2; + + var oldpos = _position; + var oldcolumn = _column; + + while (IsBinaryDigit(Current()) || Current() == '_') + { + Advance(); + _column++; + } + + return new Token(TokenType.BinNumber, + _document.Text.Slice(oldpos, _position - oldpos).ToString().Replace("_", string.Empty), oldpos, _position, + _line, oldcolumn); + } + + private Token LexCharLiteral() + { + var oldpos = ++_position; + var oldColumn = _column; + + if (Current() == '\n' || Current() == '\r') + { + var range = new SourceRange(_document, _column, 1); + Messages.Add(Message.Error(ErrorID.UnterminatedCharLiteral, range)); + + return Token.Invalid; + } + + while (Peek() != '\'' && Peek() != '\0') + { + Advance(); + _column++; + } + + _column += 2; + + return new Token(TokenType.CharLiteral, _document.Text.Slice(oldpos, _position - oldpos).ToString(), oldpos - 1, + ++_position, _line, oldColumn); + } + + private Token LexDecimalNumber() + { + var oldpos = _position; + var oldcolumn = _column; + + while (char.IsDigit(Current())) + { + _position++; + _column++; + } + + if (char.IsDigit(Peek(1)) && Current() == '.') + { + Advance(); + _column++; + + while (char.IsDigit(Current())) + { + Advance(); + _column++; + } + } + + return new Token(TokenType.Number, _document.Text.Slice(oldpos, _position - oldpos).ToString(), oldpos, + _position, _line, oldcolumn); + } + + private Token LexDoubleQuoteString() + { + var oldpos = ++_position; + var oldColumn = _column; + + while (Peek() != '"' && Peek() != '\0') + { + if (Current() == '\n' || Current() == '\r') + { + var range = new SourceRange(_document, _position, 1); + Messages.Add(Message.Error(ErrorID.UnterminatedStringLiteral, range)); + + return new Token(TokenType.StringLiteral, + _document.Text.Slice(oldpos, _position - oldpos - 1).ToString(), oldpos - 1, _position, _line, + oldColumn); + } + + Advance(); + _column++; + } + + _column += 2; + + return new Token(TokenType.StringLiteral, _document.Text.Slice(oldpos, _position - oldpos).ToString(), + oldpos - 1, ++_position, _line, oldColumn); + } + + private Token LexHexNumber() + { + _position += 2; + _column += 2; + + var oldpos = _position; + var oldcolumn = _column; + + while (IsHex(Current()) || Current() == '_') + { + Advance(); + _column++; + } + + return new Token(TokenType.HexNumber, + _document.Text.Slice(oldpos, _position - oldpos).ToString().Replace("_", string.Empty), oldpos, _position, + _line, oldcolumn); + } + + private Token LexIdentifier() + { + var oldpos = _position; + + var oldcolumn = _column; + while (IsIdentifierDigit()) + { + Advance(); + _column++; + } + + var tokenText = _document.Text.Slice(oldpos, _position - oldpos).ToString(); + + return new Token(TokenUtils.GetTokenType(tokenText), tokenText, oldpos, _position, _line, oldcolumn); + } + + private Token LexSymbol(KeyValuePair symbol) + { + var oldpos = _position; + + _position += symbol.Key.Length; + _column += symbol.Key.Length; + + var text = _document.Text.Slice(oldpos, symbol.Key.Length).ToString(); + + return new Token(_symbolTokens[text], text, oldpos, _position, _line, _column); + } + + private void SkipComments() + { + while (IsMatch("/*") || IsMatch("//")) + { + if (IsMatch("//")) + { + Advance(); + Advance(); + _column++; + _column++; + + while (Current() != '\n' && Current() != '\r' && Current() != '\0') + { + Advance(); + _column++; + } + + if (Current() == '\n' || Current() == '\r') + { + Advance(); + _column++; + } + + SkipWhitespaces(); + } + else if (IsMatch("/*")) + { + var oldpos = _position; + + Advance(); + Advance(); + _column++; + _column++; + + while (!IsMatch("*/")) + { + if (Current() == '\0') + { + break; + } + + Advance(); + _column++; + } + + if (IsMatch("*/")) + { + Advance(); + _column++; + + Advance(); + _column++; + } + else + { + var range = new SourceRange(_document, oldpos, _position); + Messages.Add(Message.Error(ErrorID.NotClosedMultilineComment, range)); + + return; + } + + SkipWhitespaces(); + } + } + } + + private void SkipWhitespaces() + { + while (char.IsWhiteSpace(Current()) && _position <= _document.Text.Count) + { + if (Current() == '\r') + { + _line++; + _column = 1; + Advance(); + + if (Current() == '\n') + { + Advance(); + } + } + else + { + Advance(); + _column++; + } + } + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Message.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Message.cs new file mode 100644 index 0000000..f145c4e --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Message.cs @@ -0,0 +1,61 @@ +using Backlang.Codeanalysis.Core; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public enum MessageSeverity +{ + Error, Warning, Info, Hint +} + +public sealed class Message +{ + public Message(MessageSeverity severity, string text, SourceRange range) + { + if (range.Source is SourceFile doc) + { + Document = doc; + } + + Severity = severity; + Text = text; + Range = range; + } + + public SourceRange Range { get; set; } + + public SourceFile Document { get; } + + public MessageSeverity Severity { get; set; } + public string Text { get; set; } + + public static Message Error(LocalizableString message, SourceRange range) + { + return new Message(MessageSeverity.Error, message, range); + } + + public static Message Error(LocalizableString message) + { + return new Message(MessageSeverity.Error, message, SourceRange.Synthetic); + } + + public static Message Info(string message, SourceRange range) + { + return new Message(MessageSeverity.Info, message, range); + } + + public static Message Warning(string message, SourceRange range) + { + return new Message(MessageSeverity.Warning, message, range); + } + + public override string ToString() + { + if (Document == null) + { + return Text; + } + + return $"{Document.FileName}:{Range.Start.Line}:{Range.Start.Column} {Text}"; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/OperatorInfo.cs b/NewSource/Backlang.CodeAnalysis/Parsing/OperatorInfo.cs new file mode 100644 index 0000000..9c74e8b --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/OperatorInfo.cs @@ -0,0 +1,3 @@ +namespace Backlang.Codeanalysis.Parsing; + +public record struct OperatorInfo(TokenType TokenType, int Precedence, bool IsUnary, bool IsPostUnary); \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/ParsePoints.cs b/NewSource/Backlang.CodeAnalysis/Parsing/ParsePoints.cs new file mode 100644 index 0000000..fa71aaa --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/ParsePoints.cs @@ -0,0 +1,7 @@ +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed class ParsePoints : Dictionary> +{ +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Parser.Expressions.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Parser.Expressions.cs new file mode 100644 index 0000000..f9e0d81 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Parser.Expressions.cs @@ -0,0 +1,213 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Parsing.AST; +using Loyc; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed partial class Parser +{ + private readonly Dictionary _lits = new() + { + { "ub", CodeSymbols.UInt8 }, + { "us", CodeSymbols.UInt16 }, + { "u", CodeSymbols.UInt32 }, + { "ui", CodeSymbols.UInt32 }, + { "ul", CodeSymbols.UInt64 }, + { "b", CodeSymbols.Int8 }, + { "s", CodeSymbols.Int16 }, + { "l", CodeSymbols.Int64 }, + { "h", Symbols.Float16 }, + { "f", Symbols.Float32 }, + { "d", Symbols.Float64 } + }; + + public void AddError(LocalizableString message, SourceRange range) + { + Messages.Add(Message.Error(message, range)); + } + + public void AddError(LocalizableString message) + { + Messages.Add(Message.Error(message, + new SourceRange(Document, Iterator.Current.Start, Iterator.Current.Text.Length))); + } + + internal LNode ParsePrimary(ParsePoints parsePoints = null) + { + parsePoints ??= ExpressionParsePoints; + + return Iterator.Current.Type switch + { + TokenType.StringLiteral => ParseString(), + TokenType.CharLiteral => ParseChar(), + TokenType.Number => ParseNumber(), + TokenType.HexNumber => ParseHexNumber(), + TokenType.BinNumber => ParseBinNumber(), + TokenType.TrueLiteral => ParseBooleanLiteral(true), + TokenType.FalseLiteral => ParseBooleanLiteral(false), + TokenType.OpenSquare => ParseArrayLiteral(), + _ => InvokeExpressionParsePoint(parsePoints) + }; + } + + private LNode ParseArrayLiteral() + { + var startToken = Iterator.Current; + Iterator.NextToken(); + + var elements = Expression.ParseList(this, TokenType.CloseSquare); + + return SyntaxTree.Factory.Call(CodeSymbols.Array, elements).WithRange(startToken, Iterator.Prev); + } + + private LNode Invalid(LocalizableString message) + { + AddError(message); + + return LNode.Call(CodeSymbols.Error, LNode.List(LNode.Literal(message))); + } + + private LNode InvokeExpressionParsePoint(ParsePoints parsePoints) + { + var token = Iterator.Current; + var type = token.Type; + + if (parsePoints.TryGetValue(type, out var value)) + { + Iterator.NextToken(); + + return value(Iterator, this).WithRange(token, Iterator.Prev); + } + + if (type == Token.Invalid.Type) + { + return LNode.Missing; + } + + return Invalid(ErrorID.UnknownExpression); + } + + private LNode ParseBinNumber() + { + var valueToken = (UString)Iterator.NextToken().Text; + + var success = ParseHelpers.TryParseUInt(ref valueToken, out ulong result, 2, ParseNumberFlag.SkipUnderscores); + + if (!success) + { + return LNode.Missing; + } + + return SyntaxTree.Factory.Call(CodeSymbols.Int32, + LNode.List(SyntaxTree.Factory.Literal(result).WithStyle(NodeStyle.BinaryLiteral))) + .WithRange(Iterator.Prev); + } + + private LNode ParseBooleanLiteral(bool value) + { + Iterator.NextToken(); + + return SyntaxTree.Factory.Call(CodeSymbols.Bool, LNode.List(SyntaxTree.Factory.Literal(value))) + .WithRange(Iterator.Prev); + } + + private LNode ParseChar() + { + var text = Iterator.NextToken().Text; + var unescaped = ParseHelpers.UnescapeCStyle(text); + + return SyntaxTree.Factory.Call(CodeSymbols.Char, + LNode.List(SyntaxTree.Factory.Literal(unescaped[0]))).WithRange(Iterator.Prev); + } + + private LNode ParseHexNumber() + { + var valueToken = Iterator.NextToken(); + + var parseSuccess = ParseHelpers.TryParseHex(valueToken.Text, out var result); + + if (!parseSuccess) + { + return LNode.Missing; + } + + return SyntaxTree.Factory.Call(CodeSymbols.Int32, + LNode.List(SyntaxTree.Factory.Literal(result))) + .WithRange(Iterator.Prev); + } + + private LNode ParseNumber() + { + var text = (UString)Iterator.NextToken().Text; + + LNode result; + if (text.Contains('.')) + { + var value = ParseHelpers.TryParseDouble(ref text, 10, ParseNumberFlag.SkipUnderscores); + + result = SyntaxTree.Factory.Literal(value).WithRange(Iterator.Prev); + } + else + { + var success = ParseHelpers.TryParseInt(ref text, out int value, 10, ParseNumberFlag.SkipUnderscores); + + if (!success) + { + result = LNode.Missing; + } + else + { + result = SyntaxTree.Factory.Literal(value).WithRange(Iterator.Prev); + } + } + + if (Iterator.Current.Type == TokenType.Identifier) + { + if (_lits.TryGetValue(Iterator.Current.Text.ToLower(), out var value)) + { + result = SyntaxTree.Factory.Call(value, + LNode.List(result)).WithRange(Iterator.Prev, Iterator.Current); + } + else + { + AddError(new LocalizableString(ErrorID.UnknownLiteral, Iterator.Current.Text)); + + result = LNode.Missing; + } + + Iterator.NextToken(); + } + else if (result.Value is double) + { + result = SyntaxTree.Factory.Call(Symbols.Float64, LNode.List(result)).WithRange(result.Range); + } + else + { + result = SyntaxTree.Factory.Call(CodeSymbols.Int32, LNode.List(result)).WithRange(result.Range); + } + + if (Iterator.IsMatch(TokenType.LessThan)) + { + Iterator.NextToken(); + + var unit = Iterator.Match(TokenType.Identifier); + + result = SyntaxTree.Unit(result, unit.Text).WithRange(result.Range.StartIndex, unit.End); + + Iterator.Match(TokenType.GreaterThan); + } + + return result; + } + + private LNode ParseString() + { + var valueToken = Iterator.NextToken(); + + var unescaped = ParseHelpers.UnescapeCStyle(valueToken.Text); + + return SyntaxTree.Factory.Call(CodeSymbols.String, LNode.List(SyntaxTree.Factory.Literal(unescaped))) + .WithRange(valueToken); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Parser.ParsePoints.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Parser.ParsePoints.cs new file mode 100644 index 0000000..e03b0e0 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Parser.ParsePoints.cs @@ -0,0 +1,137 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Parsing.AST; +using Backlang.Codeanalysis.Parsing.AST.Declarations; +using Backlang.Codeanalysis.Parsing.AST.Expressions; +using Backlang.Codeanalysis.Parsing.AST.Expressions.Match; +using Backlang.Codeanalysis.Parsing.AST.Statements; +using Backlang.Codeanalysis.Parsing.AST.Statements.Loops; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed partial class Parser +{ + public readonly ParsePoints DeclarationParsePoints = new(); + public readonly ParsePoints ExpressionParsePoints = new(); + public readonly ParsePoints StatementParsePoints = new(); + + public void InitParsePoints() + { + AddDeclarationParsePoint(TokenType.Bitfield); + AddDeclarationParsePoint(TokenType.Union); + AddDeclarationParsePoint(TokenType.Class); + AddDeclarationParsePoint(TokenType.Constructor); + AddDeclarationParsePoint(TokenType.Destructor); + AddDeclarationParsePoint(TokenType.Type); + AddDeclarationParsePoint(TokenType.Enum); + AddDeclarationParsePoint(TokenType.Function); + AddDeclarationParsePoint(TokenType.Macro); + AddDeclarationParsePoint(TokenType.Interface); + AddDeclarationParsePoint(TokenType.Implement); + AddDeclarationParsePoint(TokenType.Import); + AddDeclarationParsePoint(TokenType.Struct); + AddDeclarationParsePoint(TokenType.Module); + AddDeclarationParsePoint(TokenType.Using); + AddDeclarationParsePoint(TokenType.Unit); + AddDeclarationParsePoint(TokenType.Identifier); + + AddExpressionParsePoint(TokenType.Identifier); + AddExpressionParsePoint(TokenType.OpenParen); + AddExpressionParsePoint(TokenType.Match); + AddExpressionParsePoint(TokenType.Default); + AddExpressionParsePoint(TokenType.SizeOf); + AddExpressionParsePoint(TokenType.TypeOf); + AddExpressionParsePoint(TokenType.None); + AddExpressionParsePoint(TokenType.OpenSquare); + + AddStatementParsePoint(TokenType.Throw); + AddStatementParsePoint(TokenType.Break); + AddStatementParsePoint(TokenType.Continue); + AddStatementParsePoint(TokenType.Return); + AddStatementParsePoint(TokenType.Let); + AddStatementParsePoint(TokenType.Switch); + AddStatementParsePoint(TokenType.If); + AddStatementParsePoint(TokenType.While); + AddStatementParsePoint(TokenType.Do); + AddStatementParsePoint(TokenType.Try); + AddStatementParsePoint(TokenType.For); + AddStatementParsePoint(TokenType.Identifier); + } + + public void AddDeclarationParsePoint(TokenType type) + where T : IParsePoint + { + DeclarationParsePoints.Add(type, T.Parse); + } + + public void AddExpressionParsePoint(TokenType type) + where T : IParsePoint + { + ExpressionParsePoints.Add(type, T.Parse); + } + + public void AddStatementParsePoint(TokenType type) + where T : IParsePoint + { + StatementParsePoints.Add(type, T.Parse); + } + + public LNodeList InvokeDeclarationParsePoints(TokenType terminator = TokenType.EOF, ParsePoints parsePoints = null) + { + if (parsePoints == null) + { + parsePoints = DeclarationParsePoints; + } + + var body = new LNodeList(); + while (Iterator.Current.Type != terminator) + { + DocComment.TryParse(this, out var docComment); + Annotation.TryParse(this, out var annotation); + Modifier.TryParse(this, out var modifiers); + + var item = InvokeParsePoint(parsePoints)?.PlusAttrs(annotation).PlusAttrs(modifiers).PlusAttr(docComment); + + if (item != null) + { + body.Add(item); + } + } + + return body; + } + + public LNode InvokeParsePoint(ParsePoints parsePoints) + { + var type = Iterator.Current.Type; + + if (parsePoints.ContainsKey(type)) + { + Iterator.NextToken(); + + return parsePoints[type](Iterator, this); + } + + var range = new SourceRange(Document, Iterator.Current.Start, Iterator.Current.Text.Length); + + AddError(new LocalizableString(ErrorID.UnknownExpression, Iterator.Current.Text), range); + + Iterator.NextToken(); + + return default; + } + + public LNode InvokeStatementParsePoint() + { + var type = Iterator.Current.Type; + + if (StatementParsePoints.ContainsKey(type)) + { + Iterator.NextToken(); + + return StatementParsePoints[type](Iterator, this); + } + + return ExpressionStatement.Parse(Iterator, this); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Parser.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Parser.cs new file mode 100644 index 0000000..31c438d --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Parser.cs @@ -0,0 +1,67 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Parsing.AST; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed partial class Parser +{ + public readonly List Messages; + + public Parser(SourceFile document, List tokens, List messages) + { + Document = document; + Iterator = new TokenIterator(tokens, document); + Messages = messages; + + InitParsePoints(); + } + + public SourceFile Document { get; } + + public TokenIterator Iterator { get; set; } + + public static CompilationUnit Parse(SourceDocument src) + { + SourceFile document = src; + + if (document.Text == null) + { + return new CompilationUnit + { + Body = LNode.List(LNode.Missing), + Messages = new List { Message.Error(ErrorID.EmptyFile, SourceRange.Synthetic) }, + Document = document + }; + } + + var lexer = new Lexer(); + var tokens = lexer.Tokenize(document); + + var parser = new Parser(document, tokens, lexer.Messages); + + return parser.Program(); + } + + public CompilationUnit Program() + { + var node = Start(); + + Iterator.Match(TokenType.EOF); + + return node; + } + + private CompilationUnit Start() + { + var cu = new CompilationUnit(); + + var body = InvokeDeclarationParsePoints(); + + cu.Messages = Messages.Concat(Iterator.Messages).ToList(); + cu.Body = body; + cu.Document = Document; + + return cu; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Precedences/BinaryOpPrecedences.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Precedences/BinaryOpPrecedences.cs new file mode 100644 index 0000000..4658b0e --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Precedences/BinaryOpPrecedences.cs @@ -0,0 +1,29 @@ +namespace Backlang.Codeanalysis.Parsing.Precedences; + +public enum BinaryOpPrecedences +{ + Casting = 1, // as + + Hat = 2, + + Ampersand = 3, + + EqualsEquals = 4, + DashedOps = EqualsEquals, // add, sub + Range = DashedOps, + And = Range, // && + + DottedOps = 5, // mul, div + Percent = DottedOps, + Or = Percent, + Comparisons = Or, // < <= >= > + SwapOperator = 2, + + FunctionCalls = 7, // . :: + + PipeOperator = 8, // |> + + Dot = 8, + OperationShortcuts = 2, // += -= *= /= + Equals = OperationShortcuts +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Precedences/UnaryOpPrecedences.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Precedences/UnaryOpPrecedences.cs new file mode 100644 index 0000000..e915509 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Precedences/UnaryOpPrecedences.cs @@ -0,0 +1,14 @@ +namespace Backlang.Codeanalysis.Parsing.Precedences; + +public enum UnaryOpPrecedences +{ + Literals = 3, // u ui ub us ul b s l + + LogicalNot = 6, // !bool + Negate = LogicalNot, // -int + + Ampersand = 9, + Hat = Ampersand, + + Dollar = 10 +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/SourceDocument.cs b/NewSource/Backlang.CodeAnalysis/Parsing/SourceDocument.cs new file mode 100644 index 0000000..8f6f142 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/SourceDocument.cs @@ -0,0 +1,28 @@ +using Loyc.Syntax; +using System.Text; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed class SourceDocument +{ + private readonly SourceFile _document; + + public SourceDocument(string filename) + { + _document = new SourceFile(new StreamCharSource(File.OpenRead(filename)), filename); + } + + public SourceDocument(string filename, string content) + { + var filebody = Encoding.Default.GetBytes(content); + + _document = new SourceFile(new StreamCharSource(new MemoryStream(filebody)), filename); + } + + public static implicit operator SourceFile(SourceDocument doc) + { + SyntaxTree.Factory = new LNodeFactory(doc._document); + + return doc._document; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/SyntaxTree.cs b/NewSource/Backlang.CodeAnalysis/Parsing/SyntaxTree.cs new file mode 100644 index 0000000..ed71155 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/SyntaxTree.cs @@ -0,0 +1,271 @@ +using Backlang.Codeanalysis.Parsing.AST; +using Loyc; +using Loyc.Syntax; + +namespace Backlang.Codeanalysis.Parsing; + +public static class SyntaxTree +{ + public static LNodeFactory Factory = new(EmptySourceFile.Unknown); + + public static LNode Annotation(LNode call) + { + return Factory.Call(Symbols.Annotation).PlusAttr(call); + } + + public static LNode Constructor(LNodeList parameters, LNode code) + { + return Factory.Call(Symbols.Constructor, LNode.List(Factory.AltList(parameters), code)); + } + + public static LNode DiscriminatedType(Token nameToken, LNodeList parameters) + { + return Factory.Call(Symbols.DiscriminatedType, + LNode.List(Factory.FromToken(nameToken), Factory.AltList(parameters))); + } + + public static LNode DiscriminatedUnion(Token nameToken, LNodeList types) + { + return Factory.Call(Symbols.DiscriminatedUnion, + LNode.List(Factory.FromToken(nameToken), Factory.AltList(types))); + } + + public static LNode Property(LNode type, LNode name, LNode getter, LNode setter, LNode value) + { + if (value != null) + { + return LNode.Call(CodeSymbols.Property, + LNode.List(type, getter, setter, LNode.Call(CodeSymbols.Assign, LNode.List(name, value)))); + } + + return LNode.Call(CodeSymbols.Property, LNode.List(type, getter, setter, name)); + } + + public static LNode Destructor(LNodeList parameters, LNode code) + { + return Factory.Call(Symbols.Destructor, LNode.List(Factory.AltList(parameters), code)); + } + + public static LNode Array(LNode typeNode, int dimensions) + { + return Factory.Call(CodeSymbols.Array, LNode.List(typeNode, LNode.Literal(dimensions))); + } + + public static LNode Throw(LNode arg) + { + return Factory.Call(CodeSymbols.Throw, LNode.List(arg)); + } + + public static LNode ArrayInstantiation(LNodeList elements) + { + return Factory.Call(CodeSymbols.Braces, elements); + } + + public static LNode ArrayInstantiation(LNode arr, LNodeList indices) + { + return arr.WithArgs(indices); + } + + public static LNode Binary(Symbol op, LNode left, LNode right) + { + return Factory.Call(op, LNode.List(left, right)).SetStyle(NodeStyle.Operator); + } + + public static LNode Bitfield(Token nameToken, LNodeList members) + { + return Factory.Call(Symbols.Bitfield, LNode.List(Factory.FromToken(nameToken), Factory.AltList(members))); + } + + public static LNode Case(LNode condition, LNode body) + { + return Factory.Call(CodeSymbols.Case, LNode.List(condition, body)); + } + + public static LNode Catch(IdNode exceptionType, IdNode exceptionValueName, LNode body) + { + return Factory.Call(CodeSymbols.Catch, LNode.List(exceptionType, exceptionValueName, body)); + } + + public static LNode Class(Token nameToken, LNodeList inheritances, LNodeList members) + { + return Factory.Call(CodeSymbols.Class, + LNode.List( + Factory.FromToken(nameToken), + Factory.Call(Symbols.Inheritance, inheritances), + Factory.Call(CodeSymbols.Braces, members).SetStyle(NodeStyle.StatementBlock))); + } + + public static LNode Default() + { + return Default(LNode.Missing); + } + + public static LNode Default(LNode type) + { + return Factory.Call(CodeSymbols.Default, LNode.List(type)); + } + + public static LNode Enum(LNode name, LNodeList members) + { + return Factory.Call(CodeSymbols.Enum, Factory.AltList(name, + Factory.Call(CodeSymbols.AltList), + Factory.Call(CodeSymbols.Braces, + members))); + } + + public static LNode For(LNode init, LNode arr, LNode body) + { + return Factory.Call( + CodeSymbols.For, + Factory.AltList(Factory.AltList( + Factory.AltList(LNode.Call(CodeSymbols.In, + Factory.AltList(init, arr)).SetStyle(NodeStyle.Operator))), LNode.Missing, + Factory.AltList(), body)); + } + + public static LNode If(LNode cond, LNode ifBody, LNode elseBody) + { + return Factory.Call(CodeSymbols.If, Factory.AltList(cond, ifBody, elseBody)); + } + + public static LNode ImplDecl(LNode target, LNodeList body) + { + var attributes = new LNodeList(); + + return Factory.Call(Symbols.Implementation, + Factory.AltList(target, LNode.Call(CodeSymbols.Braces, + body).SetStyle(NodeStyle.StatementBlock))).WithAttrs(attributes); + } + + public static LNode Import(LNode expr) + { + return Factory.Call(CodeSymbols.Import, LNode.List(expr)); + } + + public static LNode Interface(Token nameToken, LNodeList inheritances, LNodeList members) + { + return Factory.Call(CodeSymbols.Interface, + LNode.List( + Factory.FromToken(nameToken), + LNode.Call(Symbols.Inheritance, inheritances), + LNode.Call(CodeSymbols.Braces, members).SetStyle(NodeStyle.StatementBlock))); + } + + public static LNode Module(LNode ns) + { + return Factory.Call(CodeSymbols.Namespace, LNode.List(ns)); + } + + public static LNode None() + { + return Factory.Call(CodeSymbols.Void, LNode.Literal(null)); + } + + public static LNode Pointer(LNode type) + { + return Factory.Call(Symbols.PointerType, LNode.List(type)); + } + + public static LNode RefType(LNode type) + { + return Factory.Call(Symbols.RefType, LNode.List(type)); + } + + public static LNode NullableType(LNode type) + { + return Factory.Call(Symbols.NullableType, LNode.List(type)); + } + + public static LNode Signature(LNode name, LNode type, LNodeList args, LNodeList generics) + { + return Factory.Call(CodeSymbols.Fn, LNode.List( + type, name, + Factory.AltList(args))).PlusAttr(LNode.Call(Symbols.Where, generics)); + } + + public static LNode SizeOf(LNode type) + { + return Factory.Call(CodeSymbols.Sizeof, LNode.List(type)); + } + + public static LNode Struct(Token nameToken, LNodeList inheritances, LNodeList members) + { + return Factory.Call(CodeSymbols.Struct, + LNode.List( + Factory.FromToken(nameToken), + Factory.Call(Symbols.Inheritance, inheritances), + Factory.Call(CodeSymbols.Braces, members).SetStyle(NodeStyle.StatementBlock))); + } + + public static LNode Switch(LNode element, LNodeList cases) + { + return Factory.Call(CodeSymbols.SwitchStmt, + LNode.List(element, LNode.Call(CodeSymbols.Braces, cases).SetStyle(NodeStyle.StatementBlock))); + } + + public static LNode Try(LNode body, LNode catches, LNode finallly) + { + return Factory.Call(CodeSymbols.Try, LNode.List( + body, + catches, + Factory.Call(CodeSymbols.Finally, LNode.List(finallly)))); + } + + public static LNode Type(string name, LNodeList arguments) + { + return Factory.Call(Symbols.TypeLiteral, + Factory.AltList(Factory.Id(name), Factory.Call(CodeSymbols.Of, arguments))); + } + + public static LNode Unary(Symbol op, LNode arg) + { + return Factory.Call(op, LNode.List(arg)).SetStyle(NodeStyle.Operator); + } + + public static LNode Union(string name, LNodeList members) + { + return Factory.Call(Symbols.Union, LNode.List(Factory.Id(name)).Add(Factory.AltList(members))); + } + + public static LNode Using(LNode expr) + { + if (!expr.Calls(CodeSymbols.As)) // TODO: throw error in intermediate stage when has only one arg + { + return Factory.Call(CodeSymbols.UsingStmt, LNode.Missing); + } + + return Factory.Call(CodeSymbols.UsingStmt, LNode.List(expr[0], expr[1])); + } + + public static LNode When(LNode binOp, LNode rightHand, LNode body) + { + return Factory.Call(CodeSymbols.When, LNode.List(binOp, rightHand, body)); + } + + public static LNode While(LNode cond, LNode body) + { + return Factory.Call( + CodeSymbols.While, + LNode.List(cond, body)); + } + + public static LNode Unit(LNode result, string unit) + { + return Factory.Call(Symbols.Unit, LNode.List(result, LNode.Id(unit))); + } + + public static LNode UnitDeclaration(Token nameToken) + { + return Factory.Call(Symbols.UnitDecl, LNode.List(Factory.FromToken(nameToken))); + } + + public static LNode TypeOfExpression(LNode type) + { + return Factory.Call(CodeSymbols.Typeof, LNode.List(type)); + } + + public static LNode DoWhile(LNode body, LNode cond) + { + return Factory.Call(CodeSymbols.DoWhile, LNode.List(body, cond)); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/Token.cs b/NewSource/Backlang.CodeAnalysis/Parsing/Token.cs new file mode 100644 index 0000000..0f38815 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/Token.cs @@ -0,0 +1,41 @@ +namespace Backlang.Codeanalysis.Parsing; + +public sealed class Token +{ + public static Token Invalid = new(TokenType.Invalid); + + public Token(TokenType type, string text, int start, int end, int line, int column) + { + Type = type; + Text = text; + Start = start; + End = end; + Line = line; + Column = column; + } + + public Token(TokenType type) + { + Type = type; + Text = string.Empty; + } + + public Token(TokenType type, string text) + { + Type = type; + Text = text; + } + + public int Column { get; } + public int End { get; set; } + public int Line { get; set; } + public int Start { get; set; } + public string Text { get; set; } + + public TokenType Type { get; set; } + + public override string ToString() + { + return Text; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/TokenIterator.cs b/NewSource/Backlang.CodeAnalysis/Parsing/TokenIterator.cs new file mode 100644 index 0000000..b17d1c5 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/TokenIterator.cs @@ -0,0 +1,107 @@ +using Backlang.Codeanalysis.Core; +using Backlang.Codeanalysis.Core.Attributes; +using Loyc.Syntax; +using System.Reflection; + +namespace Backlang.Codeanalysis.Parsing; + +public sealed class TokenIterator +{ + private readonly SourceFile _document; + private readonly List _tokens; + public readonly List Messages = new(); + + public TokenIterator(List tokens, SourceFile document) + { + _tokens = tokens; + _document = document; + } + + public Token Current => Peek(0); + public int Position { get; set; } + public Token Prev => Peek(-1); + + public static string GetTokenRepresentation(TokenType kind) + { + var field = kind.GetType().GetField(Enum.GetName(kind)); + + var lexeme = field.GetCustomAttribute(); + var keyword = field.GetCustomAttribute(); + + if (lexeme is not null) + { + return lexeme.Lexeme; + } + + if (keyword is not null) + { + return keyword.Keyword; + } + + return Enum.GetName(kind); + } + + public bool ConsumeIfMatch(TokenType kind) + { + var result = false; + if (IsMatch(kind)) + { + result = true; + NextToken(); + } + + return result; + } + + public bool IsMatch(TokenType kind) + { + return Current.Type == kind; + } + + public bool IsMatch(params TokenType[] kinds) + { + var result = false; + foreach (var kind in kinds) + { + result |= IsMatch(kind); + } + + return result; + } + + public Token Match(TokenType kind) + { + if (Current.Type == kind) + { + return NextToken(); + } + + Messages.Add( + Message.Error( + new LocalizableString(ErrorID.Expected, GetTokenRepresentation(kind), + GetTokenRepresentation(Current.Type)), + new SourceRange(_document, Current.Start, Current.Text.Length))); + + NextToken(); + + return Token.Invalid; + } + + public Token NextToken() + { + var current = Current; + Position++; + return current; + } + + public Token Peek(int offset) + { + var index = Position + offset; + if (index >= _tokens.Count) + { + return _tokens[_tokens.Count - 1]; + } + + return _tokens[index]; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/TokenType.cs b/NewSource/Backlang.CodeAnalysis/Parsing/TokenType.cs new file mode 100644 index 0000000..707e599 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/TokenType.cs @@ -0,0 +1,260 @@ +using Backlang.Codeanalysis.Core.Attributes; +using Backlang.Codeanalysis.Parsing.Precedences; + +namespace Backlang.Codeanalysis.Parsing; + +public enum TokenType +{ + Invalid, + EOF, + Identifier, + StringLiteral, + Number, + HexNumber, + BinNumber, + CharLiteral, + + [Lexeme(".")] [BinaryOperatorInfo(BinaryOpPrecedences.Dot)] + Dot, + + [Lexeme("::")] [BinaryOperatorInfo(BinaryOpPrecedences.FunctionCalls)] + ColonColon, + + [BinaryOperatorInfo(BinaryOpPrecedences.DashedOps)] [Lexeme("+")] + Plus, + + [BinaryOperatorInfo(BinaryOpPrecedences.Range)] [Lexeme("..")] + RangeOperator, + + [PreUnaryOperatorInfo(UnaryOpPrecedences.Negate)] [BinaryOperatorInfo(BinaryOpPrecedences.DashedOps)] [Lexeme("-")] + Minus, + + [Lexeme("&")] + [PreUnaryOperatorInfo(UnaryOpPrecedences.Ampersand)] + [BinaryOperatorInfo(BinaryOpPrecedences.Ampersand)] + Ampersand, + + [Lexeme("|")] [BinaryOperatorInfo(BinaryOpPrecedences.Ampersand)] + Pipe, + + [Lexeme("~")] [PreUnaryOperatorInfo(UnaryOpPrecedences.LogicalNot)] + Tilde, + + [Lexeme("^")] [BinaryOperatorInfo(BinaryOpPrecedences.Hat)] [PreUnaryOperatorInfo(UnaryOpPrecedences.Hat)] + Hat, + + [BinaryOperatorInfo(BinaryOpPrecedences.DottedOps)] [Lexeme("/")] + Slash, + + [BinaryOperatorInfo(BinaryOpPrecedences.DottedOps)] [PreUnaryOperatorInfo(UnaryOpPrecedences.Hat)] [Lexeme("*")] + Star, + + [PostUnaryOperatorInfo(UnaryOpPrecedences.Negate)] [Lexeme(".*")] + DotAsterisk, // for namespace imports + + [BinaryOperatorInfo(BinaryOpPrecedences.Hat)] [Lexeme("**")] + StarStar, + + [BinaryOperatorInfo(BinaryOpPrecedences.Percent)] [PostUnaryOperatorInfo(UnaryOpPrecedences.Literals)] [Lexeme("%")] + Percent, + + [BinaryOperatorInfo(BinaryOpPrecedences.And)] [Lexeme("and")] [Lexeme("&&")] + And, + + [BinaryOperatorInfo(BinaryOpPrecedences.Or)] [Lexeme("or")] [Lexeme("||")] + Or, + + [PreUnaryOperatorInfo(UnaryOpPrecedences.LogicalNot)] [Lexeme("!")] + Exclamation, + + [Lexeme("*=")] + [Lexeme("/=")] + [Lexeme("+=")] + [Lexeme("-=")] + [Lexeme("|=")] + [Lexeme("&=")] + [Lexeme("!!=")] + [BinaryOperatorInfo(BinaryOpPrecedences.OperationShortcuts)] + EqualsShortcutToken, + + [Lexeme("=")] [BinaryOperatorInfo(BinaryOpPrecedences.Equals)] + EqualsToken, + + [Lexeme("<=")] [BinaryOperatorInfo(BinaryOpPrecedences.Comparisons)] + LessThanEqual, + + [Lexeme("<")] [BinaryOperatorInfo(BinaryOpPrecedences.Comparisons)] + LessThan, + + [Lexeme(">")] [BinaryOperatorInfo(BinaryOpPrecedences.Comparisons)] + GreaterThan, + + [Lexeme(">=")] [BinaryOperatorInfo(BinaryOpPrecedences.Comparisons)] + GreaterThanEqual, + + [Lexeme(":")] Colon, + + [Lexeme("(")] OpenParen, + + [Lexeme(")")] CloseParen, + + [Lexeme("{")] OpenCurly, + + [Lexeme("}")] CloseCurly, + + [Lexeme("->")] Arrow, + + [Lexeme("=>")] GoesTo, + + [Lexeme("|>")] [BinaryOperatorInfo(BinaryOpPrecedences.PipeOperator)] + PipeOperator, + + [Lexeme(",")] Comma, + + [Lexeme("$")] [PreUnaryOperatorInfo(UnaryOpPrecedences.Dollar)] + Dollar, + + [Lexeme("?")] [PostUnaryOperatorInfo(UnaryOpPrecedences.Negate)] + Questionmark, + + [Lexeme("==")] [BinaryOperatorInfo(BinaryOpPrecedences.EqualsEquals)] + EqualsEquals, + + [Lexeme("!=")] [BinaryOperatorInfo(BinaryOpPrecedences.EqualsEquals)] + NotEquals, + + [Lexeme("<->")] [BinaryOperatorInfo(BinaryOpPrecedences.SwapOperator)] + SwapOperator, + + [Lexeme("_")] Underscore, + + [Lexeme(";")] Semicolon, + + [Lexeme("[")] OpenSquare, + + [Lexeme("]")] CloseSquare, + + [Lexeme("@")] At, + + [Lexeme("as")] [BinaryOperatorInfo(BinaryOpPrecedences.Casting)] + As, + + [Keyword("true")] TrueLiteral, + + [Keyword("false")] FalseLiteral, + + [Keyword("type")] Type, + + [Keyword("func")] Function, + + [Keyword("constructor")] Constructor, + + [Keyword("destructor")] Destructor, + + [Keyword("macro")] Macro, + + [Keyword("let")] Let, + + [Keyword("prop")] Property, + + [Keyword("mut")] Mutable, + + [Keyword("enum")] Enum, + + [Keyword("try")] Try, + + [Keyword("catch")] Catch, + + [Keyword("finally")] Finally, + + [Keyword("with")] With, + + [Keyword("match")] Match, + + [Keyword("struct")] Struct, + + [Keyword("class")] Class, + + [Keyword("interface")] Interface, + + [Keyword("bitfield")] Bitfield, + + [Keyword("default")] Default, + + [Keyword("sizeof")] SizeOf, + + [Keyword("typeof")] TypeOf, + + [Keyword("none")] None, + + [Keyword("get")] Get, + + [Keyword("set")] Set, + + [Keyword("init")] Init, + + [Keyword("switch")] Switch, + + [Keyword("case")] Case, + + [Keyword("break")] Break, + + [Keyword("continue")] Continue, + + [Keyword("return")] Return, + + [Keyword("when")] When, + + [Keyword("where")] Where, + + [Keyword("if")] If, + + [Keyword("else")] Else, + + [Keyword("while")] While, + + [Keyword("do")] Do, + + [Keyword("in")] In, + + [Keyword("for")] For, + + [Keyword("const")] Const, + + [Keyword("global")] Global, + + [Keyword("static")] Static, + + [Keyword("abstract")] Abstract, + + [Keyword("extern")] Extern, + + [Keyword("override")] Override, + + [Keyword("of")] Of, + + [Keyword("implement")] Implement, + + [Keyword("operator")] Operator, + + [Keyword("public")] Public, + + [Keyword("internal")] Internal, + + [Keyword("protected")] Protected, + + [Keyword("private")] Private, + + [Keyword("import")] Import, + + [Keyword("module")] Module, + + [Keyword("using")] Using, + + [Keyword("union")] Union, + + [Keyword("throw")] Throw, + + [Keyword("unit")] Unit, + DocComment +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Parsing/TokenUtils.cs b/NewSource/Backlang.CodeAnalysis/Parsing/TokenUtils.cs new file mode 100644 index 0000000..7d382b2 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Parsing/TokenUtils.cs @@ -0,0 +1,56 @@ +using Backlang.Codeanalysis.Core.Attributes; +using System.Reflection; + +namespace Backlang.Codeanalysis.Parsing; + +public static class TokenUtils +{ + private static readonly Dictionary TokenTypeRepresentations = new(StringComparer.Ordinal); + + static TokenUtils() + { + var typeValues = (TokenType[])Enum.GetValues(typeof(TokenType)); + + foreach (var keyword in typeValues) + { + var attributes = keyword.GetType().GetField(Enum.GetName(keyword)) + .GetCustomAttributes(true); + + if (attributes != null && attributes.Any()) + { + foreach (var attribute in attributes) + { + TokenTypeRepresentations.Add(attribute.Keyword, keyword); + } + } + } + } + + public static TokenType GetTokenType(string text) + { + if (TokenTypeRepresentations.ContainsKey(text)) + { + return TokenTypeRepresentations[text]; + } + + return TokenType.Identifier; + } + + public static bool IsOperator(this Token token) + { + //var op = token.Type; + //var attributes = op.GetType().GetField(Enum.GetName(op)).GetCustomAttributes(true); + //return attributes != null && attributes.Any(); + if (Expression.BinaryOperators.ContainsKey(token.Type)) + { + return true; + } + + if (Expression.PreUnaryOperators.ContainsKey(token.Type)) + { + return true; + } + + return Expression.PostUnaryOperators.ContainsKey(token.Type); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.CodeAnalysis/Properties/Resources.Designer.cs b/NewSource/Backlang.CodeAnalysis/Properties/Resources.Designer.cs new file mode 100644 index 0000000..5940499 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Properties/Resources.Designer.cs @@ -0,0 +1,350 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Backlang.Codeanalysis.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Backlang.CodeAnalysis.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Expected Identifier, TupleType or Function-Signature as TypeLiteral, but got {0}. + /// + internal static string BL_0001_ { + get { + return ResourceManager.GetString("BL(0001)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid Modifier Combination. + /// + internal static string BL_0002_ { + get { + return ResourceManager.GetString("BL(0002)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown Character '{0}'. + /// + internal static string BL_0003_ { + get { + return ResourceManager.GetString("BL(0003)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unterminated Char-Literal. + /// + internal static string BL_0004_ { + get { + return ResourceManager.GetString("BL(0004)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected Expression {0}. + /// + internal static string BL_0005_ { + get { + return ResourceManager.GetString("BL(0005)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown Literal {0}. + /// + internal static string BL_0006_ { + get { + return ResourceManager.GetString("BL(0006)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trailing comma is forbidden. + /// + internal static string BL_0007_ { + get { + return ResourceManager.GetString("BL(0007)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bitfield member declaration only allows literals. + /// + internal static string BL_0008_ { + get { + return ResourceManager.GetString("BL(0008)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expected Function, Property or Field-declaration for Type, but got {0}. + /// + internal static string BL_0009_ { + get { + return ResourceManager.GetString("BL(0009)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expected Type but got {0}. + /// + internal static string BL_0010_ { + get { + return ResourceManager.GetString("BL(0010)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unexpected Switch Option. + /// + internal static string BL_0011_ { + get { + return ResourceManager.GetString("BL(0011)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expected at least one catch block. + /// + internal static string BL_0012_ { + get { + return ResourceManager.GetString("BL(0012)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SourceFile is empty. + /// + internal static string BL_0013_ { + get { + return ResourceManager.GetString("BL(0013)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expected Identifier but got {0}. + /// + internal static string BL_0014_ { + get { + return ResourceManager.GetString("BL(0014)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unterminated String-Literal. + /// + internal static string BL_0015_ { + get { + return ResourceManager.GetString("BL(0015)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Multiline comment is not closed. + /// + internal static string BL_0016_ { + get { + return ResourceManager.GetString("BL(0016)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Expected '{0}' but got '{1}'. + /// + internal static string BL_0017_ { + get { + return ResourceManager.GetString("BL(0017)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Duplicate Modifier '{0}'. + /// + internal static string BL_0018_ { + get { + return ResourceManager.GetString("BL(0018)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Namespace '{0}' already imported. + /// + internal static string BL_0019_ { + get { + return ResourceManager.GetString("BL(0019)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Got OutputType 'Exe' but couldn't find entry point.. + /// + internal static string BL_0020_ { + get { + return ResourceManager.GetString("BL(0020)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} cannot be found. Did you mean '{1}'?. + /// + internal static string BL_0021_ { + get { + return ResourceManager.GetString("BL(0021)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot implement '{0}', type not found. + /// + internal static string BL_0022_ { + get { + return ResourceManager.GetString("BL(0022)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot implement unit type '{0}'. + /// + internal static string BL_0023_ { + get { + return ResourceManager.GetString("BL(0023)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to '{0}' already declared. + /// + internal static string BL_0024_ { + get { + return ResourceManager.GetString("BL(0024)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type mismatch {0} {1}. + /// + internal static string BL_0025_ { + get { + return ResourceManager.GetString("BL(0025)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unit Type mismatch {0} {1}. + /// + internal static string BL_0026_ { + get { + return ResourceManager.GetString("BL(0026)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} cannot be resolved. + /// + internal static string BL_0027_ { + get { + return ResourceManager.GetString("BL(0027)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot find function '{0}'. + /// + internal static string BL_0028_ { + get { + return ResourceManager.GetString("BL(0028)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Target '{0}' cannot be found. + /// + internal static string BL_0029_ { + get { + return ResourceManager.GetString("BL(0029)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Identifier '{0}' is not defined. + /// + internal static string BL_0030_ { + get { + return ResourceManager.GetString("BL(0030)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot set type. + /// + internal static string BL_0031_ { + get { + return ResourceManager.GetString("BL(0031)", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cannot deduce Type. Declare it manually!. + /// + internal static string BL_0032_ { + get { + return ResourceManager.GetString("BL(0032)", resourceCulture); + } + } + } +} diff --git a/NewSource/Backlang.CodeAnalysis/Properties/Resources.resx b/NewSource/Backlang.CodeAnalysis/Properties/Resources.resx new file mode 100644 index 0000000..e2246f8 --- /dev/null +++ b/NewSource/Backlang.CodeAnalysis/Properties/Resources.resx @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, + PublicKeyToken=b77a5c561934e089 + + + + Expected Identifier, TupleType or Function-Signature as TypeLiteral, but got {0} + + + Invalid Modifier Combination + + + Unknown Character '{0}' + + + Unterminated Char-Literal + + + Unexpected Expression {0} + + + Unknown Literal {0} + + + Trailing comma is forbidden + + + Bitfield member declaration only allows literals + + + Expected Function, Property or Field-declaration for Type, but got {0} + + + Expected Type but got {0} + + + Unexpected Switch Option + + + Expected at least one catch block + + + SourceFile is empty + + + Expected Identifier but got {0} + + + Unterminated String-Literal + + + Multiline comment is not closed + + + Expected '{0}' but got '{1}' + + + Duplicate Modifier '{0}' + + + Namespace '{0}' already imported + + + Got OutputType 'Exe' but couldn't find entry point. + + + {0} cannot be found. Did you mean '{1}'? + + + Cannot implement '{0}', type not found + + + Cannot implement unit type '{0}' + + + '{0}' already declared + + + Type mismatch {0} {1} + + + Unit Type mismatch {0} {1} + + + {0} cannot be resolved + + + Cannot find function '{0}' + + + Target '{0}' cannot be found + + + Identifier '{0}' is not defined + + + Cannot set type + + + Cannot deduce Type. Declare it manually! + + \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/Backlang.Runtime.csproj b/NewSource/Backlang.Runtime/Backlang.Runtime.csproj new file mode 100644 index 0000000..49a75b8 --- /dev/null +++ b/NewSource/Backlang.Runtime/Backlang.Runtime.csproj @@ -0,0 +1,10 @@ + + + + Backlang.Core + + + + + + diff --git a/NewSource/Backlang.Runtime/CompilerService/MacroLibAttribute.cs b/NewSource/Backlang.Runtime/CompilerService/MacroLibAttribute.cs new file mode 100644 index 0000000..220b8d3 --- /dev/null +++ b/NewSource/Backlang.Runtime/CompilerService/MacroLibAttribute.cs @@ -0,0 +1,5 @@ +namespace Backlang.Core.CompilerService; + +public class MacroLibAttribute : Attribute +{ +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/CompilerService/UnitAttribute.cs b/NewSource/Backlang.Runtime/CompilerService/UnitAttribute.cs new file mode 100644 index 0000000..977a687 --- /dev/null +++ b/NewSource/Backlang.Runtime/CompilerService/UnitAttribute.cs @@ -0,0 +1,7 @@ +namespace Backlang.Core.CompilerService; + +[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.ReturnValue)] +public class UnitAttribute : Attribute +{ + public Type UnitType { get; set; } +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/CompilerService/UnitTypeAttribute.cs b/NewSource/Backlang.Runtime/CompilerService/UnitTypeAttribute.cs new file mode 100644 index 0000000..5addc85 --- /dev/null +++ b/NewSource/Backlang.Runtime/CompilerService/UnitTypeAttribute.cs @@ -0,0 +1,6 @@ +namespace Backlang.Core.CompilerService; + +[AttributeUsage(AttributeTargets.Class)] +public class UnitTypeAttribute : Attribute +{ +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/Macros/BuiltInMacros.cs b/NewSource/Backlang.Runtime/Macros/BuiltInMacros.cs new file mode 100644 index 0000000..03862fb --- /dev/null +++ b/NewSource/Backlang.Runtime/Macros/BuiltInMacros.cs @@ -0,0 +1,167 @@ +using LeMP; +using Loyc; +using Loyc.Syntax; +using System.Text; + +namespace Backlang.Core.Macros; + +[ContainsMacros] +public static partial class BuiltInMacros +{ + private static readonly LNodeFactory F = new(EmptySourceFile.Synthetic); + + [LexicalMacro("todo", "Add hint to do something", "todo")] + public static LNode Todo(LNode node, IMacroContext context) + { + if (node.ArgCount == 1) + { + var msg = node.Args[0].Args[0]; + context.Warn(msg.Value.ToString()); + } + else + { + context.Error("The ToDo macro needs a message"); + } + + return LNode.Missing; + } + + [LexicalMacro("notimplemented", "Semantic info for functionality that is not implemented", "notimplemented")] + public static LNode NotImplemented(LNode node, IMacroContext context) + { + return LNode.Missing; + } + + [LexicalMacro("refactor", "Semantic info for functionality that needs to be refactored", "refactor")] + public static LNode Refactor(LNode node, IMacroContext context) + { + return LNode.Missing; + } + + [LexicalMacro(@"nameof(id_or_expr)", + @"Converts the 'key' name component of an expression to a string (e.g. nameof(A.B(D)) == ""B"")", "nameof", + Mode = MacroMode.MatchIdentifierOrCall)] + public static LNode Nameof(LNode nameof, IMacroContext context) + { + if (nameof.ArgCount != 1) + { + return null; + } + + var arg = nameof.Args[0]; + if (arg.IsCall) + { + if (arg.Name == (Symbol)".") + { + if (arg.Args[1].IsCall) + { + return F.Literal(arg.Args[1].Name); + } + + return arg.Args[1]; + } + + if (arg.Name == (Symbol)"::") + { + if (arg.Args[1].IsCall) + { + return F.Literal(arg.Args[1].Name); + } + + return arg.Args[1]; + } + + if (arg.Target.IsId) + { + return arg.Target; + } + } + + return arg; + } + + [LexicalMacro("concatId(id, id)", "Concats 2 Ids to a new Id (eg. concatId(a, b) == ab)", "concatId", + Mode = MacroMode.MatchIdentifierOrCall)] + public static LNode concatId(LNode concatID, IMacroContext context) + { + if (concatID.ArgCount < 2) + { + return null; + } + + var sb = new StringBuilder(); + + foreach (var arg in concatID.Args) + { + if (arg.IsId) + { + sb.Append(arg.Name.Name); + } + else + { + context.Sink.Warning(arg, "Argument is not an Id"); + } + } + + return F.Id(sb.ToString()); + } + + [LexicalMacro("$variableName", + "Expands a variable (scoped property) assigned by a macro such as `static deconstruct()` or `static tryDeconstruct()`.", + "'$", Mode = MacroMode.Passive)] + public static LNode DollarSignVariable(LNode node, IMacroContext context) + { + LNode id; + if (node.ArgCount == 1 && (id = node.Args[0]).IsId && !id.HasPAttrs()) + { + object value; + if (context.ScopedProperties.TryGetValue("$" + id.Name.Name, out value)) + { + if (value is LNode) + { + return ((LNode)value).WithRange(id.Range); + } + + context.Sink.Warning(id, "The specified scoped property is not a syntax tree. " + + "Use `#getScopedProperty({0})` to insert it as a literal.", id.Name); + } + else + { + context.Sink.Error(id, "There is no macro property in scope named `{0}`", id.Name); + } + } + + return null; + } + + [LexicalMacro("left <-> right", "Swaps the values of the two variables", "'<->", + Mode = MacroMode.MatchIdentifierOrCall)] + public static LNode Swap(LNode node, IMacroContext context) + { + var left = node.Args[0]; + var right = node.Args[1]; + var temp = GenerateId(null, context); + + return LNode.Call(CodeSymbols.Braces, LNode.List( + LNode.Call(CodeSymbols.Var, + LNode.List(LNode.Missing, LNode.Call(CodeSymbols.Assign, LNode.List(temp, left)))), + LNode.Call(CodeSymbols.Assign, LNode.List(left, right)), + LNode.Call(CodeSymbols.Assign, LNode.List(right, temp)) + )).SetStyle(NodeStyle.StatementBlock); + } + + [LexicalMacro("generateId()", "Generates a new Id (eg. generateId() == a0)", "generateId", + Mode = MacroMode.MatchIdentifierOrCall)] + public static LNode GenerateId(LNode generateID, IMacroContext context) + { + var alphabet = "abcdefghijklmnopqrstuvwxyz_"; + + var sb = new StringBuilder(); + for (var i = 0; i < 3; i++) + { + sb.Append(Random.Shared.Next(0, alphabet.Length)); + } + + return F.Id("_" + sb + context.IncrementTempCounter()); + } +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/Macros/QuoteMacro.cs b/NewSource/Backlang.Runtime/Macros/QuoteMacro.cs new file mode 100644 index 0000000..5e885cc --- /dev/null +++ b/NewSource/Backlang.Runtime/Macros/QuoteMacro.cs @@ -0,0 +1,309 @@ +using LeMP; +using Loyc; +using Loyc.Syntax; +using System.Reflection; +using S = Loyc.Syntax.CodeSymbols; + +namespace Backlang.Core.Macros; + +public partial class BuiltInMacros +{ + private static readonly LNode _CodeSymbols = F.Id("CodeSymbols"); + + private static Dictionary CodeSymbolTable; + + [LexicalMacro("quote(code); quote { code(); }", + "Macro-based code quote mechanism, to be used as long as a more complete compiler is not availabe. " + + "If there is a single parameter that is braces, the braces are stripped out. " + + "If there are multiple parameters, or multiple statements in braces, the result is a call to #splice(). " + + "The output refers unqualified to `CodeSymbols` and `LNode` so you must have 'using Loyc.Syntax' at the top of your file. " + + "The substitution operator $(expr) causes the specified expression to be inserted unchanged into the output.", + "quote", "#quote")] + public static LNode Quote(LNode node, IMessageSink sink) + { + return Quote(node, true, true); + } + + /// + /// This implements `quote` and related macros. It converts a + /// Loyc tree (e.g. `Foo(this)`) into a piece of .NET code that can + /// construct the essence of the same tree (e.g. + /// `LNode.Call((Symbol) "Foo", LNode.List(LNode.Id(CodeSymbols.This)));`), + /// although this code does not preserve the Range properties. + /// + /// If this flag is true, when a calls to + /// @`'$` is encountered, it is treated as a substitution request, + /// e.g. $node causes node to be included unchanged in the + /// output, and by example, Foo($x, $(..list)) produces this tree: + /// LNode.Call((Symbol) "Foo", LNode.List().Add(x).AddRange(list)). + /// + /// + /// If this flag is true, the output expression + /// does not construct trivia attributes. + /// + /// The quoted form. + public static LNode Quote(LNode node, bool allowSubstitutions, bool ignoreTrivia) + { + LNode code = node, arg; + if (code.ArgCount == 1 && (arg = code.Args[0]).Calls(S.Braces) && !arg.HasPAttrs()) + { + // Braces are needed to allow statement syntax in EC#; they are + // not necessarily desired in the output, so ignore them. The user + // can still write quote {{...}} to include braces in the output. + code = arg; + } + + return new CodeQuoter(allowSubstitutions, ignoreTrivia).Quote(code.Args.AsLNode(S.Splice)); + } + + [LexicalMacro( + @"e.g. quoteWithTrivia(/* cool! */ $foo) ==> foo.PlusAttrs(LNode.List(LNode.Trivia(CodeSymbols.TriviaMLComment, "" cool! "")))", + "Behaves the same as quote(code) except that trivia is included in the output.")] + public static LNode QuoteWithTrivia(LNode node, IMessageSink sink) + { + return Quote(node, true, false); + } + + [LexicalMacro(@"e.g. rawQuote($foo) ==> F.Call(CodeSymbols.Substitute, F.Id(""foo""));", + "Behaves the same as quote(code) except that the substitution operator $ is not recognized as a request for substitution.", + "rawQuote", "#rawQuote")] + public static LNode RawQuote(LNode node, IMessageSink sink) + { + return Quote(node, false, true); + } + + [LexicalMacro( + @"e.g. rawQuoteWithTrivia(/* cool! */ $foo) ==> LNode.Call(LNode.List(LNode.Trivia(CodeSymbols.TriviaMLComment, "" cool! "")), CodeSymbols.Substitute, LNode.List(LNode.Id((Symbol) ""foo"")))", + "Behaves the same as rawQuote(code) except that trivia is included in the output.")] + public static LNode RawQuoteWithTrivia(LNode node, IMessageSink sink) + { + return Quote(node, false, false); + } + + internal static LNode QuoteSymbol(Symbol name) + { + if (CodeSymbolTable == null) + { + CodeSymbolTable = FindStaticReadOnlies(typeof(CodeSymbols), fInfo => !fInfo.Name.StartsWith("_")); + } + + if (CodeSymbolTable.TryGetValue(name, out var field)) + { + return F.Dot(_CodeSymbols, F.Id(field)); + } + + return F.Call(S.Cast, F.Literal(name.Name), F.Id("Symbol")); + } + + /// + /// Helper function that finds the static readonly fields of a given + /// type in a given class, and creates a table from the _values_ of those + /// fields to the _names_ of those fields. + /// + private static Dictionary FindStaticReadOnlies(Type type, Predicate filter = null) + { + var dict = new Dictionary(); + var list = type.GetFields(BindingFlags.Static | BindingFlags.Public) + .Where(field => typeof(T).IsAssignableFrom(field.FieldType) && field.IsInitOnly + && field.GetCustomAttributes( + typeof(ObsoleteAttribute), true).Length == + 0); + foreach (var field in list) + { + if (filter == null || filter(field)) + { + dict[(T)field.GetValue(null)] = GSymbol.Get(field.Name); + } + } + + return dict; + } + + public class CodeQuoter + { + private static readonly LNode CodeSymbols_Splice = F.Dot(_CodeSymbols, F.Id("Splice")); + + private static readonly LNode Id_LNode = F.Id("LNode"); + + private static readonly LNode Id_PlusAttrs = F.Id("PlusAttrs"); + + private static readonly LNode LNode_Braces = F.Dot(Id_LNode, F.Id("Braces")); + + private static readonly LNode LNode_Call = F.Dot(Id_LNode, F.Id("Call")); + + private static readonly LNode LNode_Dot = F.Dot(Id_LNode, F.Id("Dot")); + + private static readonly LNode LNode_Id = F.Dot(Id_LNode, F.Id("Id")); + + private static readonly LNode LNode_InParensTrivia = F.Dot(Id_LNode, F.Id("InParensTrivia")); + + private static readonly LNode LNode_List = F.Dot(Id_LNode, F.Id("List")); + + private static readonly LNode LNode_Literal = F.Dot(Id_LNode, F.Id("Literal")); + + private static readonly LNode LNode_Missing = F.Dot(Id_LNode, F.Id("Missing")); + + private static readonly LNode LNode_Trivia = F.Dot(Id_LNode, F.Id("Trivia")); + public bool _doSubstitutions; + public bool _ignoreTrivia; + + public CodeQuoter( + bool doSubstitutions, + bool ignoreTrivia = true) + { + _doSubstitutions = doSubstitutions; + _ignoreTrivia = ignoreTrivia; + } + + public LNode Quote(LNode node) + { + if (node.Equals(LNode.InParensTrivia)) + { + return LNode_InParensTrivia; + } + + if (node.Equals(LNode.Missing)) + { + return LNode_Missing; + } + + var creationArgs = new LNodeList(); + + // Translate attributes (if any) + var attrList = MaybeQuoteList(node.Attrs, true); + if (attrList != null) + { + creationArgs.Add(attrList); + } + + LNode result; + switch (node.Kind) + { + case LNodeKind.Literal: // => F.Literal(value) + creationArgs.Add(node.WithoutAttrs()); + result = F.Call(LNode_Literal, creationArgs); + break; + + case LNodeKind.Id: // => F.Id(string), F.Id(CodeSymbols.Name) + creationArgs.Add(QuoteSymbol(node.Name)); + result = F.Call(LNode_Id, creationArgs); + break; + + default: // NodeKind.Call => F.Dot(...), F.Of(...), F.Call(...), F.Braces(...) + var preserveStyle = true; + if (_doSubstitutions && node.Calls(S.Substitute, 1)) + { + preserveStyle = false; + result = node.Args[0]; + if (attrList != null) + { + if (result.IsCall) + { + result = result.InParens(); + } + + result = F.Call(F.Dot(result, Id_PlusAttrs), attrList); + } + } + else if (!_ignoreTrivia && node.ArgCount == 1 && node.TriviaValue != NoValue.Value && + node.Target.IsId) + { + // LNode.Trivia(Symbol, object) + result = F.Call(LNode_Trivia, QuoteSymbol(node.Name), F.Literal(node.TriviaValue)); + } + /*else if (node.Calls(S.Braces)) // F.Braces(...) + result = F.Call(LNode_Braces, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions))); + else if (node.Calls(S.Dot) && node.ArgCount.IsInRange(1, 2)) + result = F.Call(LNode_Dot, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions))); + else if (node.Calls(S.Of)) + result = F.Call(LNode_Of, node.Args.SmartSelect(arg => QuoteOne(arg, substitutions)));*/ + else + { + // General case: F.Call(, ) + if (node.Target.IsId) + { + creationArgs.Add(QuoteSymbol(node.Name)); + } + else + { + creationArgs.Add(Quote(node.Target)); + } + + var argList = MaybeQuoteList(node.Args); + if (argList != null) + { + creationArgs.Add(argList); + } + + result = F.Call(LNode_Call, creationArgs); + } + + // Note: don't preserve prefix notation because if $op is +, + // we want $op(x, y) to generate code for x + y (there is no + // way to express this with infix notation.) + if (preserveStyle && node.BaseStyle != NodeStyle.Default && + node.BaseStyle != NodeStyle.PrefixNotation) + { + result = F.Call(F.Dot(result, F.Id("SetStyle")), + F.Dot(F.Id("NodeStyle"), F.Id(node.BaseStyle.ToString()))); + } + + break; + } + + return result; + } + + private static LNode VarArgExpr(LNode arg) + { + LNode subj; + if (arg.Calls(S.Substitute, 1) && ((subj = arg.Args[0]).Calls(S.DotDot, 1) || subj.Calls(S.DotDotDot, 1))) + { + return subj.Args[0]; + } + + return null; + } + + private LNode MaybeQuoteList(LNodeList list, bool isAttributes = false) + { + if (isAttributes && _ignoreTrivia) + { + list = list.SmartWhere(n => !n.IsTrivia || n.IsIdNamed(S.TriviaInParens)); + } + + if (list.IsEmpty) + { + return null; + } + + if (_doSubstitutions && list.Any(a => VarArgExpr(a) != null)) + { + if (list.Count == 1) + { + return F.Call(LNode_List, VarArgExpr(list[0])); + } + + // If you write something like quote(Foo($x, $(...y), $z)), a special + // output style is used to accommodate the variable argument list. + var argList = F.Call(LNode_List); + foreach (var arg in list) + { + var vae = VarArgExpr(arg); + if (vae != null) + { + argList = F.Call(F.Dot(argList, F.Id("AddRange")), vae); + } + else + { + argList = F.Call(F.Dot(argList, F.Id("Add")), Quote(arg)); + } + } + + return argList; + } + + return F.Call(LNode_List, list.SmartSelect(item => Quote(item))); + } + } +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/Result.cs b/NewSource/Backlang.Runtime/Result.cs new file mode 100644 index 0000000..dd073c2 --- /dev/null +++ b/NewSource/Backlang.Runtime/Result.cs @@ -0,0 +1,25 @@ +using System.Runtime.CompilerServices; + +namespace Backlang.Core; + +public class Result +{ + private readonly T? _value; + + public Result(T value) + { + _value = value; + } + + public static implicit operator T(Result value) + { + return value._value; + } + + //Unpacking operator + [SpecialName] + public static bool op_Unpacking(Result value) + { + return value._value != null; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/Sealed.cs b/NewSource/Backlang.Runtime/Sealed.cs new file mode 100644 index 0000000..ecca4c7 --- /dev/null +++ b/NewSource/Backlang.Runtime/Sealed.cs @@ -0,0 +1,47 @@ +using System.Runtime.CompilerServices; + +namespace Backlang.Core; + +public struct Sealed +{ + private T _value; + + public bool IsFreezed { get; private set; } + + public static implicit operator Sealed(T value) + { + return new Sealed { _value = value, IsFreezed = true }; + } + + public static implicit operator T(Sealed @sealed) + { + return @sealed._value; + } + + public void Set(T value) + { + if (IsFreezed) + { + throw new InvalidOperationException("Object is freezed"); + } + + _value = value; + } + + public void Freeze() + { + IsFreezed = true; + } + + public void Unfreeze() + { + IsFreezed = false; + } + + //Unpacking operator + [SpecialName] + public static T op_Unpacking(Sealed value) + { + return value._value; + } +} \ No newline at end of file diff --git a/NewSource/Backlang.Runtime/logo.png b/NewSource/Backlang.Runtime/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..557ebd34254b355fc48dc18debe824d07ec6f5b5 GIT binary patch literal 31321 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 RWX#0F#PFQKhm(#E{|_JJ(U|}M literal 0 HcmV?d00001 diff --git a/NewSource/Backlang.sln b/NewSource/Backlang.sln new file mode 100644 index 0000000..61e8188 --- /dev/null +++ b/NewSource/Backlang.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backlang.Sdk", "Backlang.Build.Tasks\Backlang.Sdk.csproj", "{1E995EBC-5334-47BC-96DA-DB5DE279A21A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BacklangC", "BacklangC\BacklangC.csproj", "{894B5A3D-2408-4CA0-A7FA-6D795DB1EE35}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backlang.CodeAnalysis", "Backlang.CodeAnalysis\Backlang.CodeAnalysis.csproj", "{49EAB195-353E-4F75-B0C0-EC8E84665BA3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Backlang.Runtime", "Backlang.Runtime\Backlang.Runtime.csproj", "{9DA0B4F1-029B-4481-A28F-4205159BD39B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1E995EBC-5334-47BC-96DA-DB5DE279A21A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E995EBC-5334-47BC-96DA-DB5DE279A21A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E995EBC-5334-47BC-96DA-DB5DE279A21A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E995EBC-5334-47BC-96DA-DB5DE279A21A}.Release|Any CPU.Build.0 = Release|Any CPU + {894B5A3D-2408-4CA0-A7FA-6D795DB1EE35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {894B5A3D-2408-4CA0-A7FA-6D795DB1EE35}.Debug|Any CPU.Build.0 = Debug|Any CPU + {894B5A3D-2408-4CA0-A7FA-6D795DB1EE35}.Release|Any CPU.ActiveCfg = Release|Any CPU + {894B5A3D-2408-4CA0-A7FA-6D795DB1EE35}.Release|Any CPU.Build.0 = Release|Any CPU + {49EAB195-353E-4F75-B0C0-EC8E84665BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49EAB195-353E-4F75-B0C0-EC8E84665BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49EAB195-353E-4F75-B0C0-EC8E84665BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49EAB195-353E-4F75-B0C0-EC8E84665BA3}.Release|Any CPU.Build.0 = Release|Any CPU + {9DA0B4F1-029B-4481-A28F-4205159BD39B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DA0B4F1-029B-4481-A28F-4205159BD39B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DA0B4F1-029B-4481-A28F-4205159BD39B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DA0B4F1-029B-4481-A28F-4205159BD39B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + EndGlobalSection +EndGlobal diff --git a/NewSource/BacklangC/BacklangC.csproj b/NewSource/BacklangC/BacklangC.csproj new file mode 100644 index 0000000..d2ba121 --- /dev/null +++ b/NewSource/BacklangC/BacklangC.csproj @@ -0,0 +1,30 @@ + + + + Exe + + true + backc + true + + + + + + + + + + + + + + Always + + + + + + + + diff --git a/NewSource/BacklangC/Driver.cs b/NewSource/BacklangC/Driver.cs new file mode 100644 index 0000000..7ba92f3 --- /dev/null +++ b/NewSource/BacklangC/Driver.cs @@ -0,0 +1,99 @@ +using System.Reflection; +using Backlang.Codeanalysis.Parsing; +using Backlang.Codeanalysis.Parsing.AST; +using BacklangC.Stages; +using DistIL; +using DistIL.AsmIO; +using Flo; + +namespace BacklangC; + +public class Driver +{ + public DriverSettings Settings { get; private init; } = new(); + public required Compilation Compilation { get; set; } + public required TypeDef ProgramType { get; set; } + + public Optimizer Optimizer { get; set; } + public List Messages { get; set; } = []; + public List Trees { get; set; } = []; + + public static Driver Create(DriverSettings settings) + { + var moduleResolver = new ModuleResolver(); + moduleResolver.AddTrustedSearchPaths(); + + var module = moduleResolver.Create(settings.RootNamespace, Version.Parse(settings.Version)); + + var compilation = new Compilation(module, new ConsoleLogger(), new CompilationSettings()); + var optimizer = new Optimizer(); + optimizer.CreatePassManager(compilation); + + var programType = module.CreateType(settings.RootNamespace, "Program", TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed); + + return new Driver + { + Compilation = compilation, + Settings = settings, + Optimizer = optimizer, + ProgramType = programType + }; + } + + public void Compile() + { + var hasError = (List messages) => messages.Any(_ => _.Severity == MessageSeverity.Error); + + var pipeline = Pipeline.Build( + cfg => { + cfg.Add(); + cfg.Add(); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.Add(); + + /*cfg.When(_ => !hasError(_.Messages) && _.Options.OutputTree, _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => !hasError(_.Messages), _ => { + _.Add(); + }); + + cfg.When(_ => _.Messages.Any(), _ => { + _.Add(); + }); + */ + } + ); + + pipeline.Invoke(this); + } +} \ No newline at end of file diff --git a/NewSource/BacklangC/DriverSettings.cs b/NewSource/BacklangC/DriverSettings.cs new file mode 100644 index 0000000..1f20dad --- /dev/null +++ b/NewSource/BacklangC/DriverSettings.cs @@ -0,0 +1,36 @@ +using CommandLine; + +namespace BacklangC; + +public class DriverSettings +{ + [Option("debug-symbols", Required = false, HelpText = "Enable debug symbols.")] + public bool DebugSymbols { get; set; } + + [Option("is-debug", Required = false, HelpText = "Specify if in debug mode.")] + public bool IsDebug { get; set; } + + public bool Optimize => OptimizeLevel != "O0"; + + [Value(0, MetaName = "sources", HelpText = "Input source files.", Required = true)] + [Option('s')] + public IEnumerable Sources { get; set; } = new List(); + + [Option('m')] + public IEnumerable? MacroReferences { get; set; } = new List(); + + [Option("output-path", Default = "compiled.dll", HelpText = "Output path for the compiled file.")] + public string OutputPath { get; set; } + + [Option("root-namespace", Default = "Compiled", HelpText = "Root namespace for the project.")] + public string RootNamespace { get; set; } + + [Option("version", Default = "1.0", HelpText = "Version of the project.")] + public string Version { get; set; } + + [Option('o', "level", Default = "-O0", HelpText = "Optimization level.")] + public string OptimizeLevel { get; set; } + + [Option('e', "exclude", Separator = ',', HelpText = "Comma-separated list of passes to exclude.")] + public IEnumerable ExcludedPasses { get; set; } = new List(); +} \ No newline at end of file diff --git a/NewSource/BacklangC/OptimizationLevel.cs b/NewSource/BacklangC/OptimizationLevel.cs new file mode 100644 index 0000000..db1506b --- /dev/null +++ b/NewSource/BacklangC/OptimizationLevel.cs @@ -0,0 +1,44 @@ +using System.Text; +using DistIL.Passes; + +namespace BacklangC; + +public class OptimizationLevel(string level) +{ + public string Level { get; } = level; + public List Passes { get; } = new(); + + public void AddPass(OptimizationPass pass) + { + Passes.Add(pass); + } + + public void AddPass(IMethodPass pass) + { + var mp = new OptimizationPass(ConvertToKebabCase(pass.GetType().Name)) + { + Pass = pass + }; + + AddPass(mp); + } + + private static string ConvertToKebabCase(string input) + { + var result = new StringBuilder(); + + for (int i = 0; i < input.Length; i++) + { + var currentChar = input[i]; + + if (char.IsUpper(currentChar) && i > 0) + { + result.Append('-'); + } + + result.Append(char.ToLower(currentChar)); + } + + return result.ToString(); + } +} \ No newline at end of file diff --git a/NewSource/BacklangC/OptimizationPass.cs b/NewSource/BacklangC/OptimizationPass.cs new file mode 100644 index 0000000..74268b8 --- /dev/null +++ b/NewSource/BacklangC/OptimizationPass.cs @@ -0,0 +1,11 @@ +using DistIL.Passes; + +namespace BacklangC; + +public class OptimizationPass(string name) +{ + public string Name { get; } = name; + public bool IsEnabled { get; set; } = true; + + public IMethodPass Pass { get; set; } +} \ No newline at end of file diff --git a/NewSource/BacklangC/Optimizer.cs b/NewSource/BacklangC/Optimizer.cs new file mode 100644 index 0000000..d52f084 --- /dev/null +++ b/NewSource/BacklangC/Optimizer.cs @@ -0,0 +1,94 @@ +using DistIL; +using DistIL.Passes; + +namespace BacklangC; + +public class Optimizer +{ + private readonly Dictionary _levels; + + public PassManager PassManager { get; set; } + + public Optimizer() + { + _levels = new Dictionary + { + { "O0", new OptimizationLevel("O0") }, + { "O1", new OptimizationLevel("O1") }, + { "O2", new OptimizationLevel("O2") }, + { "O3", new OptimizationLevel("O3") } + }; + + // Define passes + foreach (var level in _levels.Values) + { + level.AddPass(new DeadCodeElim()); + level.AddPass(new SimplifyCFG()); + } + } + + public void SetOptimizationLevel(string level) + { + if (_levels.TryGetValue(level, out var level1)) + { + Console.WriteLine($"Setting optimization level: {level}"); + // Enable all passes for this level + foreach (var pass in level1.Passes) + { + pass.IsEnabled = true; + } + } + else + { + Console.WriteLine("Invalid optimization level."); + } + } + + public void ExcludePass(string passName) + { + foreach (var level in _levels.Values) + { + var pass = level.Passes.Find(p => p.Name.Equals(passName, StringComparison.OrdinalIgnoreCase)); + + if (pass != null) + { + pass.IsEnabled = false; + } + } + } + + public void DisplayActivePasses() + { + foreach (var level in _levels.Values) + { + Console.WriteLine($"Optimization Level: {level.Level}"); + foreach (var pass in level.Passes) + { + Console.WriteLine(pass.IsEnabled ? $" - Active Pass: {pass.Name}" : $" - Excluded Pass: {pass.Name}"); + } + } + } + + public void CreatePassManager(Compilation compilation) + { + var pm = new PassManager + { + Compilation = compilation + }; + + var passes = pm.AddPasses(); + + foreach (var level in _levels.Values) + { + foreach (var pass in level.Passes) + { + if (pass.IsEnabled) + { + passes.Apply(pass.Pass); + } + } + } + + PassManager = pm; + } +} \ No newline at end of file diff --git a/NewSource/BacklangC/Program.cs b/NewSource/BacklangC/Program.cs new file mode 100644 index 0000000..ede858c --- /dev/null +++ b/NewSource/BacklangC/Program.cs @@ -0,0 +1,29 @@ +using System.Reflection; +using CommandLine; +using Parser = CommandLine.Parser; + +namespace BacklangC; + +public static class Program +{ + public static void Main(string[] args) + { + //hack + var a = Assembly.LoadFrom("Backlang.CodeAnalysis.dll"); + + Parser.Default.ParseArguments(args) + .WithParsed(options => + { + var driver = Driver.Create(options); + + driver.Compile(); + }) + .WithNotParsed(errors => + { + foreach (var error in errors) + { + Console.WriteLine(error.ToString()); + } + }); + } +} \ No newline at end of file diff --git a/NewSource/Directory.Build.props b/NewSource/Directory.Build.props new file mode 100644 index 0000000..0cce1ab --- /dev/null +++ b/NewSource/Directory.Build.props @@ -0,0 +1,20 @@ + + + + 2.0.0 + net9.0 + enable + preview + True + True + Furesoft, Backlang-Org + https://www.backlang-org/ + logo.png + https://github.com/Backlang-Org/Backlang + backlang + True + The Backlang Compiler Chain + enable + + + \ No newline at end of file diff --git a/NewSource/Directory.Build.targets b/NewSource/Directory.Build.targets new file mode 100644 index 0000000..dd635aa --- /dev/null +++ b/NewSource/Directory.Build.targets @@ -0,0 +1,10 @@ + + + + + True + \ + + + + \ No newline at end of file diff --git a/NewSource/README.md b/NewSource/README.md new file mode 100644 index 0000000..6c1d3d7 --- /dev/null +++ b/NewSource/README.md @@ -0,0 +1,6 @@ +## Installation + +## Usage +````shell +dotnet new lsdk -l:Backlang -ext:.back +```` \ No newline at end of file diff --git a/NewSource/logo.png b/NewSource/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..557ebd34254b355fc48dc18debe824d07ec6f5b5 GIT binary patch literal 31321 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 RWX#0F#PFQKhm(#E{|_JJ(U|}M literal 0 HcmV?d00001