├── .vscode
├── extensions.json
└── launch.json
├── samples
├── hello
│ ├── hello.ms
│ └── hello.msproj
├── Directory.Build.props
├── samples.sln
└── Directory.Build.targets
├── msi.cmd
├── msc.cmd
├── msi.sh
├── msc.sh
├── src
├── msi
│ ├── Program.cs
│ ├── Authoring
│ │ ├── Classification.cs
│ │ ├── ClassifiedSpan.cs
│ │ └── Classifier.cs
│ └── msi.csproj
├── Minsk
│ ├── CodeAnalysis
│ │ ├── Symbols
│ │ │ ├── SymbolKind.cs
│ │ │ ├── ParameterSymbol.cs
│ │ │ ├── LocalVariableSymbol.cs
│ │ │ ├── GlobalVariableSymbol.cs
│ │ │ ├── VariableSymbol.cs
│ │ │ ├── Symbol.cs
│ │ │ ├── TypeSymbol.cs
│ │ │ ├── FunctionSymbol.cs
│ │ │ ├── BuiltinFunctions.cs
│ │ │ └── SymbolPrinter.cs
│ │ ├── Binding
│ │ │ ├── BoundUnaryOperatorKind.cs
│ │ │ ├── BoundConstant.cs
│ │ │ ├── BoundStatement.cs
│ │ │ ├── BoundLabel.cs
│ │ │ ├── BoundNopStatement.cs
│ │ │ ├── BoundExpression.cs
│ │ │ ├── BoundGotoStatement.cs
│ │ │ ├── BoundLabelStatement.cs
│ │ │ ├── BoundBinaryOperatorKind.cs
│ │ │ ├── BoundReturnStatement.cs
│ │ │ ├── BoundExpressionStatement.cs
│ │ │ ├── BoundLoopStatement.cs
│ │ │ ├── BoundBlockStatement.cs
│ │ │ ├── BoundErrorExpression.cs
│ │ │ ├── BoundNode.cs
│ │ │ ├── BoundConversionExpression.cs
│ │ │ ├── BoundVariableDeclaration.cs
│ │ │ ├── BoundWhileStatement.cs
│ │ │ ├── BoundDoWhileStatement.cs
│ │ │ ├── BoundVariableExpression.cs
│ │ │ ├── BoundConditionalGotoStatement.cs
│ │ │ ├── BoundIfStatement.cs
│ │ │ ├── BoundAssignmentExpression.cs
│ │ │ ├── BoundCallExpression.cs
│ │ │ ├── BoundNodeKind.cs
│ │ │ ├── BoundUnaryExpression.cs
│ │ │ ├── BoundCompoundAssignmentExpression.cs
│ │ │ ├── BoundBinaryExpression.cs
│ │ │ ├── BoundForStatement.cs
│ │ │ ├── BoundLiteralExpression.cs
│ │ │ ├── BoundProgram.cs
│ │ │ ├── BoundGlobalScope.cs
│ │ │ ├── BoundUnaryOperator.cs
│ │ │ ├── BoundScope.cs
│ │ │ ├── Conversion.cs
│ │ │ ├── BoundBinaryOperator.cs
│ │ │ ├── ConstantFolding.cs
│ │ │ └── BoundNodeFactory.cs
│ │ ├── Syntax
│ │ │ ├── MemberSyntax.cs
│ │ │ ├── StatementSyntax.cs
│ │ │ ├── ExpressionSyntax.cs
│ │ │ ├── BreakStatementSyntax.cs
│ │ │ ├── ContinueStatementSyntax.cs
│ │ │ ├── GlobalStatementSyntax.cs
│ │ │ ├── NameExpressionSyntax.cs
│ │ │ ├── ExpressionStatementSyntax.cs
│ │ │ ├── ParameterSyntax.cs
│ │ │ ├── TypeClauseSyntax.cs
│ │ │ ├── ElseClauseSyntax.cs
│ │ │ ├── UnaryExpressionSyntax.cs
│ │ │ ├── ReturnStatementSyntax.cs
│ │ │ ├── CompilationUnitSyntax.cs
│ │ │ ├── SyntaxTrivia.cs
│ │ │ ├── BinaryExpressionSyntax.cs
│ │ │ ├── WhileStatementSyntax.cs
│ │ │ ├── AssignmentExpressionSyntax.cs
│ │ │ ├── LiteralExpressionSyntax.cs
│ │ │ ├── DoWhileStatementSyntax.cs
│ │ │ ├── BlockStatementSyntax.cs
│ │ │ ├── ParenthesizedExpressionSyntax.cs
│ │ │ ├── IfStatementSyntax.cs
│ │ │ ├── CallExpressionSyntax.cs
│ │ │ ├── VariableDeclarationSyntax.cs
│ │ │ ├── ForStatementSyntax.cs
│ │ │ ├── FunctionDeclarationSyntax.cs
│ │ │ ├── SeparatedSyntaxList.cs
│ │ │ ├── SyntaxToken.cs
│ │ │ ├── SyntaxKind.cs
│ │ │ ├── SyntaxTree.cs
│ │ │ └── SyntaxNode.cs
│ │ ├── EvaluationResult.cs
│ │ ├── DiagnosticExtensions.cs
│ │ ├── Text
│ │ │ ├── TextLocation.cs
│ │ │ ├── TextSpan.cs
│ │ │ ├── TextLine.cs
│ │ │ └── SourceText.cs
│ │ ├── Diagnostic.cs
│ │ └── Compilation.cs
│ ├── Minsk.csproj
│ └── IO
│ │ └── TextWriterExtensions.cs
├── Minsk.Generators
│ ├── Minsk.Generators.csproj
│ └── CurlyIndenter.cs
├── Directory.Build.targets
├── .editorconfig
├── msc
│ ├── msc.csproj
│ └── Program.cs
├── Minsk.Tests
│ ├── CodeAnalysis
│ │ ├── Text
│ │ │ └── SourceTextTests.cs
│ │ ├── Syntax
│ │ │ ├── SyntaxFactTests.cs
│ │ │ └── AssertingEnumerator.cs
│ │ └── AnnotatedText.cs
│ └── Minsk.Tests.csproj
├── Directory.Build.props
└── minsk.sln
├── genindex.ps1
├── .editorconfig
├── LICENSE
├── docs
├── episode-09.md
├── episode-26.md
├── episode-01.md
├── episode-05.md
├── episode-03.md
├── episode-02.md
├── episode-19.md
├── episode-13.md
├── episode-17.md
├── episode-23.md
├── episode-14.md
├── episode-06.md
├── episode-15.md
├── episode-11.md
├── episode-27.md
└── episode-25.md
├── azure-pipelines.yml
├── azure-pipelines-index.yml
├── README.md
└── .gitattributes
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "ms-dotnettools.csharp"
4 | ]
5 | }
--------------------------------------------------------------------------------
/samples/hello/hello.ms:
--------------------------------------------------------------------------------
1 | function main()
2 | {
3 | print("What's your name?")
4 | let name = input()
5 | print("Hello " + name + "!")
6 | }
7 |
--------------------------------------------------------------------------------
/msi.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | REM Vars
4 | set "SLNDIR=%~dp0src"
5 |
6 | REM Restore + Build
7 | dotnet build "%SLNDIR%\msi" --nologo || exit /b
8 |
9 | REM Run
10 | dotnet run -p "%SLNDIR%\msi" --no-build
11 |
--------------------------------------------------------------------------------
/samples/hello/hello.msproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp3.1
6 |
7 |
8 |
--------------------------------------------------------------------------------
/msc.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | REM Vars
4 | set "SLNDIR=%~dp0src"
5 |
6 | REM Restore + Build
7 | dotnet build "%SLNDIR%\msc" --nologo || exit /b
8 |
9 | REM Run
10 | dotnet run -p "%SLNDIR%\msc" --no-build -- %*
11 |
--------------------------------------------------------------------------------
/msi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Vars
4 | slndir="$(dirname "${BASH_SOURCE[0]}")/src"
5 |
6 | # Restore + Build
7 | dotnet build "$slndir/msi" --nologo || exit
8 |
9 | # Run
10 | dotnet run -p "$slndir/msi" --no-build
11 |
--------------------------------------------------------------------------------
/msc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Vars
4 | slndir="$(dirname "${BASH_SOURCE[0]}")/src"
5 |
6 | # Restore + Build
7 | dotnet build "$slndir/msc" --nologo || exit
8 |
9 | # Run
10 | dotnet run -p "$slndir/msc" --no-build -- "$@"
11 |
--------------------------------------------------------------------------------
/src/msi/Program.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk
2 | {
3 | internal static class Program
4 | {
5 | private static void Main()
6 | {
7 | var repl = new MinskRepl();
8 | repl.Run();
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/SymbolKind.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Symbols
2 | {
3 | public enum SymbolKind
4 | {
5 | Function,
6 | GlobalVariable,
7 | LocalVariable,
8 | Parameter,
9 | Type,
10 | }
11 | }
--------------------------------------------------------------------------------
/src/msi/Authoring/Classification.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Authoring
2 | {
3 | public enum Classification
4 | {
5 | Text,
6 | Keyword,
7 | Identifier,
8 | Number,
9 | String,
10 | Comment
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundUnaryOperatorKind.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Binding
2 | {
3 | internal enum BoundUnaryOperatorKind
4 | {
5 | Identity,
6 | Negation,
7 | LogicalNegation,
8 | OnesComplement
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/MemberSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public abstract class MemberSyntax : SyntaxNode
4 | {
5 | private protected MemberSyntax(SyntaxTree syntaxTree)
6 | : base(syntaxTree)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/StatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public abstract class StatementSyntax : SyntaxNode
4 | {
5 | private protected StatementSyntax(SyntaxTree syntaxTree)
6 | : base(syntaxTree)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public abstract class ExpressionSyntax : SyntaxNode
4 | {
5 | private protected ExpressionSyntax(SyntaxTree syntaxTree)
6 | : base(syntaxTree)
7 | {
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundConstant.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Binding
2 | {
3 | internal sealed class BoundConstant
4 | {
5 | public BoundConstant(object value)
6 | {
7 | Value = value;
8 | }
9 |
10 | public object Value { get; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal abstract class BoundStatement : BoundNode
6 | {
7 | protected BoundStatement(SyntaxNode syntax)
8 | : base(syntax)
9 | {
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundLabel.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Binding
2 | {
3 | internal sealed class BoundLabel
4 | {
5 | internal BoundLabel(string name)
6 | {
7 | Name = name;
8 | }
9 |
10 | public string Name { get; }
11 |
12 | public override string ToString() => Name;
13 | }
14 | }
--------------------------------------------------------------------------------
/genindex.ps1:
--------------------------------------------------------------------------------
1 | $indexDir = "bin\index"
2 | $toolsDir = "bin\indexTools"
3 | $zipFile = "$toolsDir\indexTools.zip"
4 | $url = "https://www.nuget.org/api/v2/package/SourceBrowser/1.0.25"
5 | $toolExe = "$toolsDir\tools\HtmlGenerator.exe"
6 | $sln = "src\minsk.sln"
7 |
8 | mkdir $toolsDir | out-null
9 | wget $url -outFile $zipFile | out-null
10 | Expand-Archive $zipFile $toolsDir | out-null
11 | & $toolExe $sln /out:$indexDir
12 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundNopStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundNopStatement : BoundStatement
6 | {
7 | public BoundNopStatement(SyntaxNode syntax)
8 | : base(syntax)
9 | {
10 | }
11 |
12 | public override BoundNodeKind Kind => BoundNodeKind.NopStatement;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Minsk.Generators/Minsk.Generators.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | false
6 | netstandard2.0
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/msi/msi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | Exe
6 | false
7 | Minsk
8 | Minsk
9 | netcoreapp3.1
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/msi/Authoring/ClassifiedSpan.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Text;
2 |
3 | namespace Minsk.CodeAnalysis.Authoring
4 | {
5 | public sealed class ClassifiedSpan
6 | {
7 | public ClassifiedSpan(TextSpan span, Classification classification)
8 | {
9 | Span = span;
10 | Classification = classification;
11 | }
12 |
13 | public TextSpan Span { get; }
14 | public Classification Classification { get; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/ParameterSymbol.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Symbols
2 | {
3 | public sealed class ParameterSymbol : LocalVariableSymbol
4 | {
5 | internal ParameterSymbol(string name, TypeSymbol type, int ordinal)
6 | : base(name, isReadOnly: true, type, null)
7 | {
8 | Ordinal = ordinal;
9 | }
10 |
11 | public override SymbolKind Kind => SymbolKind.Parameter;
12 | public int Ordinal { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/LocalVariableSymbol.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Binding;
2 |
3 | namespace Minsk.CodeAnalysis.Symbols
4 | {
5 | public class LocalVariableSymbol : VariableSymbol
6 | {
7 | internal LocalVariableSymbol(string name, bool isReadOnly, TypeSymbol type, BoundConstant? constant)
8 | : base(name, isReadOnly, type, constant)
9 | {
10 | }
11 |
12 | public override SymbolKind Kind => SymbolKind.LocalVariable;
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/GlobalVariableSymbol.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Binding;
2 |
3 | namespace Minsk.CodeAnalysis.Symbols
4 | {
5 | public sealed class GlobalVariableSymbol : VariableSymbol
6 | {
7 | internal GlobalVariableSymbol(string name, bool isReadOnly, TypeSymbol type, BoundConstant? constant)
8 | : base(name, isReadOnly, type, constant)
9 | {
10 | }
11 |
12 | public override SymbolKind Kind => SymbolKind.GlobalVariable;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/BreakStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | internal sealed partial class BreakStatementSyntax : StatementSyntax
4 | {
5 | internal BreakStatementSyntax(SyntaxTree syntaxTree, SyntaxToken keyword)
6 | : base(syntaxTree)
7 | {
8 | Keyword = keyword;
9 | }
10 |
11 | public override SyntaxKind Kind => SyntaxKind.BreakStatement;
12 | public SyntaxToken Keyword { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Minsk.CodeAnalysis.Symbols;
3 | using Minsk.CodeAnalysis.Syntax;
4 |
5 | namespace Minsk.CodeAnalysis.Binding
6 | {
7 | internal abstract class BoundExpression : BoundNode
8 | {
9 | protected BoundExpression(SyntaxNode syntax)
10 | : base(syntax)
11 | {
12 | }
13 |
14 | public abstract TypeSymbol Type { get; }
15 | public virtual BoundConstant? ConstantValue => null;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ContinueStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | internal sealed partial class ContinueStatementSyntax : StatementSyntax
4 | {
5 | internal ContinueStatementSyntax(SyntaxTree syntaxTree, SyntaxToken keyword)
6 | : base(syntaxTree)
7 | {
8 | Keyword = keyword;
9 | }
10 |
11 | public override SyntaxKind Kind => SyntaxKind.ContinueStatement;
12 | public SyntaxToken Keyword { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/GlobalStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class GlobalStatementSyntax : MemberSyntax
4 | {
5 | internal GlobalStatementSyntax(SyntaxTree syntaxTree, StatementSyntax statement)
6 | : base(syntaxTree)
7 | {
8 | Statement = statement;
9 | }
10 |
11 | public override SyntaxKind Kind => SyntaxKind.GlobalStatement;
12 | public StatementSyntax Statement { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/EvaluationResult.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using System.Linq;
3 |
4 | namespace Minsk.CodeAnalysis
5 | {
6 | public sealed class EvaluationResult
7 | {
8 | public EvaluationResult(ImmutableArray diagnostics, object? value)
9 | {
10 | Diagnostics = diagnostics;
11 | Value = value;
12 | }
13 |
14 | public ImmutableArray Diagnostics { get; }
15 | public object? Value { get; }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundGotoStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundGotoStatement : BoundStatement
6 | {
7 | public BoundGotoStatement(SyntaxNode syntax, BoundLabel label)
8 | : base(syntax)
9 | {
10 | Label = label;
11 | }
12 |
13 | public override BoundNodeKind Kind => BoundNodeKind.GotoStatement;
14 | public BoundLabel Label { get; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundLabelStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundLabelStatement : BoundStatement
6 | {
7 | public BoundLabelStatement(SyntaxNode syntax, BoundLabel label)
8 | : base(syntax)
9 | {
10 | Label = label;
11 | }
12 |
13 | public override BoundNodeKind Kind => BoundNodeKind.LabelStatement;
14 | public BoundLabel Label { get; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundBinaryOperatorKind.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Binding
2 | {
3 | internal enum BoundBinaryOperatorKind
4 | {
5 | Addition,
6 | Subtraction,
7 | Multiplication,
8 | Division,
9 | LogicalAnd,
10 | LogicalOr,
11 | BitwiseAnd,
12 | BitwiseOr,
13 | BitwiseXor,
14 | Equals,
15 | NotEquals,
16 | Less,
17 | LessOrEquals,
18 | Greater,
19 | GreaterOrEquals,
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/NameExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class NameExpressionSyntax : ExpressionSyntax
4 | {
5 | internal NameExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken identifierToken)
6 | : base(syntaxTree)
7 | {
8 | IdentifierToken = identifierToken;
9 | }
10 |
11 | public override SyntaxKind Kind => SyntaxKind.NameExpression;
12 | public SyntaxToken IdentifierToken { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ExpressionStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class ExpressionStatementSyntax : StatementSyntax
4 | {
5 | internal ExpressionStatementSyntax(SyntaxTree syntaxTree, ExpressionSyntax expression)
6 | : base(syntaxTree)
7 | {
8 | Expression = expression;
9 | }
10 |
11 | public override SyntaxKind Kind => SyntaxKind.ExpressionStatement;
12 | public ExpressionSyntax Expression { get; }
13 | }
14 | }
--------------------------------------------------------------------------------
/samples/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | .ms
5 |
6 |
7 |
11 |
12 | false
13 | false
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundReturnStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundReturnStatement : BoundStatement
6 | {
7 | public BoundReturnStatement(SyntaxNode syntax, BoundExpression? expression)
8 | : base(syntax)
9 | {
10 | Expression = expression;
11 | }
12 |
13 | public override BoundNodeKind Kind => BoundNodeKind.ReturnStatement;
14 | public BoundExpression? Expression { get; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundExpressionStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundExpressionStatement : BoundStatement
6 | {
7 | public BoundExpressionStatement(SyntaxNode syntax, BoundExpression expression)
8 | : base(syntax)
9 | {
10 | Expression = expression;
11 | }
12 |
13 | public override BoundNodeKind Kind => BoundNodeKind.ExpressionStatement;
14 | public BoundExpression Expression { get; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.{cs,vb}]
2 |
3 | dotnet_naming_rule.private_fields_start_with_underscore.symbols = private_fields
4 | dotnet_naming_rule.private_fields_start_with_underscore.style = starts_with_underscore
5 | dotnet_naming_rule.private_fields_start_with_underscore.severity = warning
6 |
7 | dotnet_naming_symbols.private_fields.applicable_kinds = field
8 | dotnet_naming_symbols.private_fields.applicable_accessibilities = private
9 |
10 | dotnet_naming_style.starts_with_underscore.capitalization = camel_case
11 | dotnet_naming_style.starts_with_underscore.required_prefix = _
12 |
--------------------------------------------------------------------------------
/src/msc/msc.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | Exe
6 | false
7 | Minsk
8 | Minsk
9 | netcoreapp3.1
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ParameterSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class ParameterSyntax : SyntaxNode
4 | {
5 | internal ParameterSyntax(SyntaxTree syntaxTree, SyntaxToken identifier, TypeClauseSyntax type)
6 | : base(syntaxTree)
7 | {
8 | Identifier = identifier;
9 | Type = type;
10 | }
11 |
12 | public override SyntaxKind Kind => SyntaxKind.Parameter;
13 | public SyntaxToken Identifier { get; }
14 | public TypeClauseSyntax Type { get; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundLoopStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal abstract class BoundLoopStatement : BoundStatement
6 | {
7 | protected BoundLoopStatement(SyntaxNode syntax, BoundLabel breakLabel, BoundLabel continueLabel)
8 | : base(syntax)
9 | {
10 | BreakLabel = breakLabel;
11 | ContinueLabel = continueLabel;
12 | }
13 |
14 | public BoundLabel BreakLabel { get; }
15 | public BoundLabel ContinueLabel { get; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Minsk.Tests/CodeAnalysis/Text/SourceTextTests.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Text;
2 | using Xunit;
3 |
4 | namespace Minsk.Tests.CodeAnalysis.Text
5 | {
6 | public class SourceTextTests
7 | {
8 | [Theory]
9 | [InlineData(".", 1)]
10 | [InlineData(".\r\n", 2)]
11 | [InlineData(".\r\n\r\n", 3)]
12 | public void SourceText_IncludesLastLine(string text, int expectedLineCount)
13 | {
14 | var sourceText = SourceText.From(text);
15 | Assert.Equal(expectedLineCount, sourceText.Lines.Length);
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/DiagnosticExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.Immutable;
3 | using System.Linq;
4 |
5 | namespace Minsk.CodeAnalysis
6 | {
7 | public static class DiagnosticExtensions
8 | {
9 | public static bool HasErrors(this ImmutableArray diagnostics)
10 | {
11 | return diagnostics.Any(d => d.IsError);
12 | }
13 |
14 | public static bool HasErrors(this IEnumerable diagnostics)
15 | {
16 | return diagnostics.Any(d => d.IsError);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/TypeClauseSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class TypeClauseSyntax : SyntaxNode
4 | {
5 | internal TypeClauseSyntax(SyntaxTree syntaxTree, SyntaxToken colonToken, SyntaxToken identifier)
6 | : base(syntaxTree)
7 | {
8 | ColonToken = colonToken;
9 | Identifier = identifier;
10 | }
11 |
12 | public override SyntaxKind Kind => SyntaxKind.TypeClause;
13 | public SyntaxToken ColonToken { get; }
14 | public SyntaxToken Identifier { get; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundBlockStatement.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | internal sealed class BoundBlockStatement : BoundStatement
7 | {
8 | public BoundBlockStatement(SyntaxNode syntax, ImmutableArray statements)
9 | : base(syntax)
10 | {
11 | Statements = statements;
12 | }
13 |
14 | public override BoundNodeKind Kind => BoundNodeKind.BlockStatement;
15 | public ImmutableArray Statements { get; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ElseClauseSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class ElseClauseSyntax : SyntaxNode
4 | {
5 | internal ElseClauseSyntax(SyntaxTree syntaxTree, SyntaxToken elseKeyword, StatementSyntax elseStatement)
6 | : base(syntaxTree)
7 | {
8 | ElseKeyword = elseKeyword;
9 | ElseStatement = elseStatement;
10 | }
11 |
12 | public override SyntaxKind Kind => SyntaxKind.ElseClause;
13 | public SyntaxToken ElseKeyword { get; }
14 | public StatementSyntax ElseStatement { get; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Minsk.Tests/Minsk.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | false
6 | netcoreapp3.1
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/UnaryExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class UnaryExpressionSyntax : ExpressionSyntax
4 | {
5 | internal UnaryExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken operatorToken, ExpressionSyntax operand)
6 | : base(syntaxTree)
7 | {
8 | OperatorToken = operatorToken;
9 | Operand = operand;
10 | }
11 |
12 | public override SyntaxKind Kind => SyntaxKind.UnaryExpression;
13 | public SyntaxToken OperatorToken { get; }
14 | public ExpressionSyntax Operand { get; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ReturnStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class ReturnStatementSyntax : StatementSyntax
4 | {
5 | internal ReturnStatementSyntax(SyntaxTree syntaxTree, SyntaxToken returnKeyword, ExpressionSyntax? expression)
6 | : base(syntaxTree)
7 | {
8 | ReturnKeyword = returnKeyword;
9 | Expression = expression;
10 | }
11 |
12 | public override SyntaxKind Kind => SyntaxKind.ReturnStatement;
13 | public SyntaxToken ReturnKeyword { get; }
14 | public ExpressionSyntax? Expression { get; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/VariableSymbol.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Minsk.CodeAnalysis.Binding;
3 |
4 | namespace Minsk.CodeAnalysis.Symbols
5 | {
6 | public abstract class VariableSymbol : Symbol
7 | {
8 | internal VariableSymbol(string name, bool isReadOnly, TypeSymbol type, BoundConstant? constant)
9 | : base(name)
10 | {
11 | IsReadOnly = isReadOnly;
12 | Type = type;
13 | Constant = isReadOnly ? constant : null;
14 | }
15 |
16 | public bool IsReadOnly { get; }
17 | public TypeSymbol Type { get; }
18 | internal BoundConstant? Constant { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Minsk/Minsk.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 | false
6 | netcoreapp3.1
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundErrorExpression.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Symbols;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | // TODO: Should the error expression accept an array of bound nodes so that we don't drop
7 | // parts of the bound tree on the floor?
8 |
9 | internal sealed class BoundErrorExpression : BoundExpression
10 | {
11 | public BoundErrorExpression(SyntaxNode syntax)
12 | : base(syntax)
13 | {
14 | }
15 |
16 | public override BoundNodeKind Kind => BoundNodeKind.ErrorExpression;
17 | public override TypeSymbol Type => TypeSymbol.Error;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundNode.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | internal abstract class BoundNode
7 | {
8 | protected BoundNode(SyntaxNode syntax)
9 | {
10 | Syntax = syntax;
11 | }
12 |
13 | public abstract BoundNodeKind Kind { get; }
14 | public SyntaxNode Syntax { get; }
15 |
16 | public override string ToString()
17 | {
18 | using (var writer = new StringWriter())
19 | {
20 | this.WriteTo(writer);
21 | return writer.ToString();
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/CompilationUnitSyntax.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 |
3 | namespace Minsk.CodeAnalysis.Syntax
4 | {
5 | public sealed partial class CompilationUnitSyntax : SyntaxNode
6 | {
7 | internal CompilationUnitSyntax(SyntaxTree syntaxTree, ImmutableArray members, SyntaxToken endOfFileToken)
8 | : base(syntaxTree)
9 | {
10 | Members = members;
11 | EndOfFileToken = endOfFileToken;
12 | }
13 |
14 | public override SyntaxKind Kind => SyntaxKind.CompilationUnit;
15 | public ImmutableArray Members { get; }
16 | public SyntaxToken EndOfFileToken { get; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundConversionExpression.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Symbols;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | internal sealed class BoundConversionExpression : BoundExpression
7 | {
8 | public BoundConversionExpression(SyntaxNode syntax, TypeSymbol type, BoundExpression expression)
9 | : base(syntax)
10 | {
11 | Type = type;
12 | Expression = expression;
13 | }
14 |
15 | public override BoundNodeKind Kind => BoundNodeKind.ConversionExpression;
16 | public override TypeSymbol Type { get; }
17 | public BoundExpression Expression { get; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/SyntaxTrivia.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Text;
2 |
3 | namespace Minsk.CodeAnalysis.Syntax
4 | {
5 | public sealed class SyntaxTrivia
6 | {
7 | internal SyntaxTrivia(SyntaxTree syntaxTree, SyntaxKind kind, int position, string text)
8 | {
9 | SyntaxTree = syntaxTree;
10 | Kind = kind;
11 | Position = position;
12 | Text = text;
13 | }
14 |
15 | public SyntaxTree SyntaxTree { get; }
16 | public SyntaxKind Kind { get; }
17 | public int Position { get; }
18 | public TextSpan Span => new TextSpan(Position, Text?.Length ?? 0);
19 | public string Text { get; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Text/TextLocation.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Text
2 | {
3 | public struct TextLocation
4 | {
5 | public TextLocation(SourceText text, TextSpan span)
6 | {
7 | Text = text;
8 | Span = span;
9 | }
10 |
11 | public SourceText Text { get; }
12 | public TextSpan Span { get; }
13 |
14 | public string FileName => Text.FileName;
15 | public int StartLine => Text.GetLineIndex(Span.Start);
16 | public int StartCharacter => Span.Start - Text.Lines[StartLine].Start;
17 | public int EndLine => Text.GetLineIndex(Span.End);
18 | public int EndCharacter => Span.End - Text.Lines[EndLine].Start;
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundVariableDeclaration.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Symbols;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | internal sealed class BoundVariableDeclaration : BoundStatement
7 | {
8 | public BoundVariableDeclaration(SyntaxNode syntax, VariableSymbol variable, BoundExpression initializer)
9 | : base(syntax)
10 | {
11 | Variable = variable;
12 | Initializer = initializer;
13 | }
14 |
15 | public override BoundNodeKind Kind => BoundNodeKind.VariableDeclaration;
16 | public VariableSymbol Variable { get; }
17 | public BoundExpression Initializer { get; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundWhileStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundWhileStatement : BoundLoopStatement
6 | {
7 | public BoundWhileStatement(SyntaxNode syntax, BoundExpression condition, BoundStatement body, BoundLabel breakLabel, BoundLabel continueLabel)
8 | : base(syntax, breakLabel, continueLabel)
9 | {
10 | Condition = condition;
11 | Body = body;
12 | }
13 |
14 | public override BoundNodeKind Kind => BoundNodeKind.WhileStatement;
15 | public BoundExpression Condition { get; }
16 | public BoundStatement Body { get; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundDoWhileStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundDoWhileStatement : BoundLoopStatement
6 | {
7 | public BoundDoWhileStatement(SyntaxNode syntax, BoundStatement body, BoundExpression condition, BoundLabel breakLabel, BoundLabel continueLabel)
8 | : base(syntax, breakLabel, continueLabel)
9 | {
10 | Body = body;
11 | Condition = condition;
12 | }
13 |
14 | public override BoundNodeKind Kind => BoundNodeKind.DoWhileStatement;
15 | public BoundStatement Body { get; }
16 | public BoundExpression Condition { get; }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/BinaryExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class BinaryExpressionSyntax : ExpressionSyntax
4 | {
5 | internal BinaryExpressionSyntax(SyntaxTree syntaxTree, ExpressionSyntax left, SyntaxToken operatorToken, ExpressionSyntax right)
6 | : base(syntaxTree)
7 | {
8 | Left = left;
9 | OperatorToken = operatorToken;
10 | Right = right;
11 | }
12 |
13 | public override SyntaxKind Kind => SyntaxKind.BinaryExpression;
14 | public ExpressionSyntax Left { get; }
15 | public SyntaxToken OperatorToken { get; }
16 | public ExpressionSyntax Right { get; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/WhileStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class WhileStatementSyntax : StatementSyntax
4 | {
5 | internal WhileStatementSyntax(SyntaxTree syntaxTree, SyntaxToken whileKeyword, ExpressionSyntax condition, StatementSyntax body)
6 | : base(syntaxTree)
7 | {
8 | WhileKeyword = whileKeyword;
9 | Condition = condition;
10 | Body = body;
11 | }
12 |
13 | public override SyntaxKind Kind => SyntaxKind.WhileStatement;
14 | public SyntaxToken WhileKeyword { get; }
15 | public ExpressionSyntax Condition { get; }
16 | public StatementSyntax Body { get; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundVariableExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Minsk.CodeAnalysis.Symbols;
3 | using Minsk.CodeAnalysis.Syntax;
4 |
5 | namespace Minsk.CodeAnalysis.Binding
6 | {
7 | internal sealed class BoundVariableExpression : BoundExpression
8 | {
9 | public BoundVariableExpression(SyntaxNode syntax, VariableSymbol variable)
10 | : base(syntax)
11 | {
12 | Variable = variable;
13 | }
14 |
15 | public override BoundNodeKind Kind => BoundNodeKind.VariableExpression;
16 | public override TypeSymbol Type => Variable.Type;
17 | public VariableSymbol Variable { get; }
18 | public override BoundConstant? ConstantValue => Variable.Constant;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/Symbol.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | namespace Minsk.CodeAnalysis.Symbols
4 | {
5 | public abstract class Symbol
6 | {
7 | private protected Symbol(string name)
8 | {
9 | Name = name;
10 | }
11 |
12 | public abstract SymbolKind Kind { get; }
13 | public string Name { get; }
14 |
15 | public void WriteTo(TextWriter writer)
16 | {
17 | SymbolPrinter.WriteTo(this, writer);
18 | }
19 |
20 | public override string ToString()
21 | {
22 | using (var writer = new StringWriter())
23 | {
24 | WriteTo(writer);
25 | return writer.ToString();
26 | }
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/TypeSymbol.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Symbols
2 | {
3 | public sealed class TypeSymbol : Symbol
4 | {
5 | public static readonly TypeSymbol Error = new TypeSymbol("?");
6 | public static readonly TypeSymbol Any = new TypeSymbol("any");
7 | public static readonly TypeSymbol Bool = new TypeSymbol("bool");
8 | public static readonly TypeSymbol Int = new TypeSymbol("int");
9 | public static readonly TypeSymbol String = new TypeSymbol("string");
10 | public static readonly TypeSymbol Void = new TypeSymbol("void");
11 |
12 | private TypeSymbol(string name)
13 | : base(name)
14 | {
15 | }
16 |
17 | public override SymbolKind Kind => SymbolKind.Type;
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundConditionalGotoStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundConditionalGotoStatement : BoundStatement
6 | {
7 | public BoundConditionalGotoStatement(SyntaxNode syntax, BoundLabel label, BoundExpression condition, bool jumpIfTrue = true)
8 | : base(syntax)
9 | {
10 | Label = label;
11 | Condition = condition;
12 | JumpIfTrue = jumpIfTrue;
13 | }
14 |
15 | public override BoundNodeKind Kind => BoundNodeKind.ConditionalGotoStatement;
16 | public BoundLabel Label { get; }
17 | public BoundExpression Condition { get; }
18 | public bool JumpIfTrue { get; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundIfStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Syntax;
2 |
3 | namespace Minsk.CodeAnalysis.Binding
4 | {
5 | internal sealed class BoundIfStatement : BoundStatement
6 | {
7 | public BoundIfStatement(SyntaxNode syntax, BoundExpression condition, BoundStatement thenStatement, BoundStatement? elseStatement)
8 | : base(syntax)
9 | {
10 | Condition = condition;
11 | ThenStatement = thenStatement;
12 | ElseStatement = elseStatement;
13 | }
14 |
15 | public override BoundNodeKind Kind => BoundNodeKind.IfStatement;
16 | public BoundExpression Condition { get; }
17 | public BoundStatement ThenStatement { get; }
18 | public BoundStatement? ElseStatement { get; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundAssignmentExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Minsk.CodeAnalysis.Symbols;
3 | using Minsk.CodeAnalysis.Syntax;
4 |
5 | namespace Minsk.CodeAnalysis.Binding
6 | {
7 | internal sealed class BoundAssignmentExpression : BoundExpression
8 | {
9 | public BoundAssignmentExpression(SyntaxNode syntax, VariableSymbol variable, BoundExpression expression)
10 | : base(syntax)
11 | {
12 | Variable = variable;
13 | Expression = expression;
14 | }
15 |
16 | public override BoundNodeKind Kind => BoundNodeKind.AssignmentExpression;
17 | public override TypeSymbol Type => Expression.Type;
18 | public VariableSymbol Variable { get; }
19 | public BoundExpression Expression { get; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/AssignmentExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class AssignmentExpressionSyntax : ExpressionSyntax
4 | {
5 | public AssignmentExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken identifierToken, SyntaxToken assignmentToken, ExpressionSyntax expression)
6 | : base(syntaxTree)
7 | {
8 | IdentifierToken = identifierToken;
9 | AssignmentToken = assignmentToken;
10 | Expression = expression;
11 | }
12 |
13 | public override SyntaxKind Kind => SyntaxKind.AssignmentExpression;
14 | public SyntaxToken IdentifierToken { get; }
15 | public SyntaxToken AssignmentToken { get; }
16 | public ExpressionSyntax Expression { get; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/LiteralExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class LiteralExpressionSyntax : ExpressionSyntax
4 | {
5 | internal LiteralExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken literalToken)
6 | : this(syntaxTree, literalToken, literalToken.Value!)
7 | {
8 | }
9 |
10 | internal LiteralExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken literalToken, object value)
11 | : base(syntaxTree)
12 | {
13 | LiteralToken = literalToken;
14 | Value = value;
15 | }
16 |
17 | public override SyntaxKind Kind => SyntaxKind.LiteralExpression;
18 | public SyntaxToken LiteralToken { get; }
19 | public object Value { get; }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Symbols/FunctionSymbol.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Symbols
5 | {
6 | public sealed class FunctionSymbol : Symbol
7 | {
8 | internal FunctionSymbol(string name, ImmutableArray parameters, TypeSymbol type, FunctionDeclarationSyntax? declaration = null)
9 | : base(name)
10 | {
11 | Parameters = parameters;
12 | Type = type;
13 | Declaration = declaration;
14 | }
15 |
16 | public override SymbolKind Kind => SymbolKind.Function;
17 | public FunctionDeclarationSyntax? Declaration { get; }
18 | public ImmutableArray Parameters { get; }
19 | public TypeSymbol Type { get; }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundCallExpression.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using Minsk.CodeAnalysis.Symbols;
3 | using Minsk.CodeAnalysis.Syntax;
4 |
5 | namespace Minsk.CodeAnalysis.Binding
6 | {
7 | internal sealed class BoundCallExpression : BoundExpression
8 | {
9 | public BoundCallExpression(SyntaxNode syntax, FunctionSymbol function, ImmutableArray arguments)
10 | : base(syntax)
11 | {
12 | Function = function;
13 | Arguments = arguments;
14 | }
15 |
16 | public override BoundNodeKind Kind => BoundNodeKind.CallExpression;
17 | public override TypeSymbol Type => Function.Type;
18 | public FunctionSymbol Function { get; }
19 | public ImmutableArray Arguments { get; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundNodeKind.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Binding
2 | {
3 | internal enum BoundNodeKind
4 | {
5 | // Statements
6 | BlockStatement,
7 | NopStatement,
8 | VariableDeclaration,
9 | IfStatement,
10 | WhileStatement,
11 | DoWhileStatement,
12 | ForStatement,
13 | LabelStatement,
14 | GotoStatement,
15 | ConditionalGotoStatement,
16 | ReturnStatement,
17 | ExpressionStatement,
18 |
19 | // Expressions
20 | ErrorExpression,
21 | LiteralExpression,
22 | VariableExpression,
23 | AssignmentExpression,
24 | CompoundAssignmentExpression,
25 | UnaryExpression,
26 | BinaryExpression,
27 | CallExpression,
28 | ConversionExpression,
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/DoWhileStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class DoWhileStatementSyntax : StatementSyntax
4 | {
5 | internal DoWhileStatementSyntax(SyntaxTree syntaxTree, SyntaxToken doKeyword, StatementSyntax body, SyntaxToken whileKeyword, ExpressionSyntax condition)
6 | : base(syntaxTree)
7 | {
8 | DoKeyword = doKeyword;
9 | Body = body;
10 | WhileKeyword = whileKeyword;
11 | Condition = condition;
12 | }
13 |
14 | public override SyntaxKind Kind => SyntaxKind.DoWhileStatement;
15 | public SyntaxToken DoKeyword { get; }
16 | public StatementSyntax Body { get; }
17 | public SyntaxToken WhileKeyword { get; }
18 | public ExpressionSyntax Condition { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/BlockStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 |
3 | namespace Minsk.CodeAnalysis.Syntax
4 | {
5 | public sealed partial class BlockStatementSyntax : StatementSyntax
6 | {
7 | internal BlockStatementSyntax(SyntaxTree syntaxTree, SyntaxToken openBraceToken, ImmutableArray statements, SyntaxToken closeBraceToken)
8 | : base(syntaxTree)
9 | {
10 | OpenBraceToken = openBraceToken;
11 | Statements = statements;
12 | CloseBraceToken = closeBraceToken;
13 | }
14 |
15 | public override SyntaxKind Kind => SyntaxKind.BlockStatement;
16 | public SyntaxToken OpenBraceToken { get; }
17 | public ImmutableArray Statements { get; }
18 | public SyntaxToken CloseBraceToken { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Text/TextSpan.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Minsk.CodeAnalysis.Text
4 | {
5 | public struct TextSpan
6 | {
7 | public TextSpan(int start, int length)
8 | {
9 | Start = start;
10 | Length = length;
11 | }
12 |
13 | public int Start { get; }
14 | public int Length { get; }
15 | public int End => Start + Length;
16 |
17 | public static TextSpan FromBounds(int start, int end)
18 | {
19 | var length = end - start;
20 | return new TextSpan(start, length);
21 | }
22 |
23 | public bool OverlapsWith(TextSpan span)
24 | {
25 | return Start < span.End &&
26 | End > span.Start;
27 | }
28 |
29 | public override string ToString() => $"{Start}..{End}";
30 | }
31 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/ParenthesizedExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class ParenthesizedExpressionSyntax : ExpressionSyntax
4 | {
5 | internal ParenthesizedExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken openParenthesisToken, ExpressionSyntax expression, SyntaxToken closeParenthesisToken)
6 | : base(syntaxTree)
7 | {
8 | OpenParenthesisToken = openParenthesisToken;
9 | Expression = expression;
10 | CloseParenthesisToken = closeParenthesisToken;
11 | }
12 |
13 | public override SyntaxKind Kind => SyntaxKind.ParenthesizedExpression;
14 | public SyntaxToken OpenParenthesisToken { get; }
15 | public ExpressionSyntax Expression { get; }
16 | public SyntaxToken CloseParenthesisToken { get; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/IfStatementSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class IfStatementSyntax : StatementSyntax
4 | {
5 | internal IfStatementSyntax(SyntaxTree syntaxTree, SyntaxToken ifKeyword, ExpressionSyntax condition, StatementSyntax thenStatement, ElseClauseSyntax? elseClause)
6 | : base(syntaxTree)
7 | {
8 | IfKeyword = ifKeyword;
9 | Condition = condition;
10 | ThenStatement = thenStatement;
11 | ElseClause = elseClause;
12 | }
13 |
14 | public override SyntaxKind Kind => SyntaxKind.IfStatement;
15 | public SyntaxToken IfKeyword { get; }
16 | public ExpressionSyntax Condition { get; }
17 | public StatementSyntax ThenStatement { get; }
18 | public ElseClauseSyntax? ElseClause { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Text/TextLine.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Text
2 | {
3 | public sealed class TextLine
4 | {
5 | public TextLine(SourceText text, int start, int length, int lengthIncludingLineBreak)
6 | {
7 | Text = text;
8 | Start = start;
9 | Length = length;
10 | LengthIncludingLineBreak = lengthIncludingLineBreak;
11 | }
12 |
13 | public SourceText Text { get; }
14 | public int Start { get; }
15 | public int Length { get; }
16 | public int End => Start + Length;
17 | public int LengthIncludingLineBreak { get; }
18 | public TextSpan Span => new TextSpan(Start, Length);
19 | public TextSpan SpanIncludingLineBreak => new TextSpan(Start, LengthIncludingLineBreak);
20 | public override string ToString() => Text.ToString(Span);
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundUnaryExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Minsk.CodeAnalysis.Symbols;
3 | using Minsk.CodeAnalysis.Syntax;
4 |
5 | namespace Minsk.CodeAnalysis.Binding
6 | {
7 | internal sealed class BoundUnaryExpression : BoundExpression
8 | {
9 | public BoundUnaryExpression(SyntaxNode syntax, BoundUnaryOperator op, BoundExpression operand)
10 | : base(syntax)
11 | {
12 | Op = op;
13 | Operand = operand;
14 | ConstantValue = ConstantFolding.Fold(op, operand);
15 | }
16 |
17 | public override BoundNodeKind Kind => BoundNodeKind.UnaryExpression;
18 | public override TypeSymbol Type => Op.Type;
19 | public BoundUnaryOperator Op { get; }
20 | public BoundExpression Operand { get; }
21 | public override BoundConstant? ConstantValue { get; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundCompoundAssignmentExpression.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Symbols;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | internal sealed class BoundCompoundAssignmentExpression : BoundExpression
7 | {
8 | public BoundCompoundAssignmentExpression(SyntaxNode syntax, VariableSymbol variable, BoundBinaryOperator op, BoundExpression expression)
9 | : base(syntax)
10 | {
11 | Variable = variable;
12 | Op = op;
13 | Expression = expression;
14 | }
15 |
16 | public override BoundNodeKind Kind => BoundNodeKind.CompoundAssignmentExpression;
17 | public override TypeSymbol Type => Expression.Type;
18 | public VariableSymbol Variable { get; }
19 | public BoundBinaryOperator Op {get; }
20 | public BoundExpression Expression { get; }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/CallExpressionSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class CallExpressionSyntax : ExpressionSyntax
4 | {
5 | internal CallExpressionSyntax(SyntaxTree syntaxTree, SyntaxToken identifier, SyntaxToken openParenthesisToken, SeparatedSyntaxList arguments, SyntaxToken closeParenthesisToken)
6 | : base(syntaxTree)
7 | {
8 | Identifier = identifier;
9 | OpenParenthesisToken = openParenthesisToken;
10 | Arguments = arguments;
11 | CloseParenthesisToken = closeParenthesisToken;
12 | }
13 |
14 | public override SyntaxKind Kind => SyntaxKind.CallExpression;
15 | public SyntaxToken Identifier { get; }
16 | public SyntaxToken OpenParenthesisToken { get; }
17 | public SeparatedSyntaxList Arguments { get; }
18 | public SyntaxToken CloseParenthesisToken { get; }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundBinaryExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Minsk.CodeAnalysis.Symbols;
3 | using Minsk.CodeAnalysis.Syntax;
4 |
5 | namespace Minsk.CodeAnalysis.Binding
6 | {
7 | internal sealed class BoundBinaryExpression : BoundExpression
8 | {
9 | public BoundBinaryExpression(SyntaxNode syntax, BoundExpression left, BoundBinaryOperator op, BoundExpression right)
10 | : base(syntax)
11 | {
12 | Left = left;
13 | Op = op;
14 | Right = right;
15 | ConstantValue = ConstantFolding.Fold(left, op, right);
16 | }
17 |
18 | public override BoundNodeKind Kind => BoundNodeKind.BinaryExpression;
19 | public override TypeSymbol Type => Op.Type;
20 | public BoundExpression Left { get; }
21 | public BoundBinaryOperator Op { get; }
22 | public BoundExpression Right { get; }
23 | public override BoundConstant? ConstantValue { get; }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Binding/BoundForStatement.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Symbols;
2 | using Minsk.CodeAnalysis.Syntax;
3 |
4 | namespace Minsk.CodeAnalysis.Binding
5 | {
6 | internal sealed class BoundForStatement : BoundLoopStatement
7 | {
8 | public BoundForStatement(SyntaxNode syntax, VariableSymbol variable, BoundExpression lowerBound, BoundExpression upperBound, BoundStatement body, BoundLabel breakLabel, BoundLabel continueLabel)
9 | : base(syntax, breakLabel, continueLabel)
10 | {
11 | Variable = variable;
12 | LowerBound = lowerBound;
13 | UpperBound = upperBound;
14 | Body = body;
15 | }
16 |
17 | public override BoundNodeKind Kind => BoundNodeKind.ForStatement;
18 | public VariableSymbol Variable { get; }
19 | public BoundExpression LowerBound { get; }
20 | public BoundExpression UpperBound { get; }
21 | public BoundStatement Body { get; }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Syntax/VariableDeclarationSyntax.cs:
--------------------------------------------------------------------------------
1 | namespace Minsk.CodeAnalysis.Syntax
2 | {
3 | public sealed partial class VariableDeclarationSyntax : StatementSyntax
4 | {
5 | internal VariableDeclarationSyntax(SyntaxTree syntaxTree, SyntaxToken keyword, SyntaxToken identifier, TypeClauseSyntax? typeClause, SyntaxToken equalsToken, ExpressionSyntax initializer)
6 | : base(syntaxTree)
7 | {
8 | Keyword = keyword;
9 | Identifier = identifier;
10 | TypeClause = typeClause;
11 | EqualsToken = equalsToken;
12 | Initializer = initializer;
13 | }
14 |
15 | public override SyntaxKind Kind => SyntaxKind.VariableDeclaration;
16 | public SyntaxToken Keyword { get; }
17 | public SyntaxToken Identifier { get; }
18 | public TypeClauseSyntax? TypeClause { get; }
19 | public SyntaxToken EqualsToken { get; }
20 | public ExpressionSyntax Initializer { get; }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Minsk/CodeAnalysis/Diagnostic.cs:
--------------------------------------------------------------------------------
1 | using Minsk.CodeAnalysis.Text;
2 |
3 | namespace Minsk.CodeAnalysis
4 | {
5 | public sealed class Diagnostic
6 | {
7 | private Diagnostic(bool isError, TextLocation location, string message)
8 | {
9 | IsError = isError;
10 | Location = location;
11 | Message = message;
12 | IsWarning = !IsError;
13 | }
14 |
15 | public bool IsError { get; }
16 | public TextLocation Location { get; }
17 | public string Message { get; }
18 | public bool IsWarning { get; }
19 |
20 | public override string ToString() => Message;
21 |
22 | public static Diagnostic Error(TextLocation location, string message)
23 | {
24 | return new Diagnostic(isError: true, location, message);
25 | }
26 |
27 | public static Diagnostic Warning(TextLocation location, string message)
28 | {
29 | return new Diagnostic(isError: false, location, message);
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/src/Minsk.Tests/CodeAnalysis/Syntax/SyntaxFactTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Minsk.CodeAnalysis.Syntax;
4 | using Xunit;
5 |
6 | namespace Minsk.Tests.CodeAnalysis.Syntax
7 | {
8 | public class SyntaxFactTests
9 | {
10 | [Theory]
11 | [MemberData(nameof(GetSyntaxKindData))]
12 | public void SyntaxFact_GetText_RoundTrips(SyntaxKind kind)
13 | {
14 | var text = SyntaxFacts.GetText(kind);
15 | if (text == null)
16 | return;
17 |
18 | var tokens = SyntaxTree.ParseTokens(text);
19 | var token = Assert.Single(tokens);
20 | Assert.Equal(kind, token.Kind);
21 | Assert.Equal(text, token.Text);
22 | }
23 |
24 | public static IEnumerable