diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index ce7dbe7c..65fd83f8 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -18,7 +18,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v2 with: - dotnet-version: 5.0.x + dotnet-version: 6.0.x - name: Cache NuGet packages uses: actions/cache@v3 with: @@ -29,14 +29,14 @@ jobs: - name: Build run: dotnet build --no-restore -c Release -v n - name: Test - run: dotnet test -c Release --no-build -v n /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura + run: dotnet test -c Release --no-build -v n /p:CollectCoverage=true /p:CoverletOutputFormat=cobertura --filter="Category=Unit" - name: Code Coverage Summary Report For Merge Request if: github.event_name == 'pull_request' uses: 5monkeys/cobertura-action@master with: path: ./Interpreter.Tests/coverage.cobertura.xml repo_token: ${{ secrets.GITHUB_TOKEN }} - minimum_coverage: 20 + minimum_coverage: 80 fail_below_threshold: true show_class_names: true show_missing: true @@ -53,5 +53,5 @@ jobs: format: markdown hide_branch_rate: true hide_complexity: true - thresholds: '20 30' + thresholds: '80 100' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3fbcd6f6..b3580a01 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v2 with: - dotnet-version: 5.0.x + dotnet-version: 6.0.x - name: Publish run: | mkdir output diff --git a/CompilersCourseWork.sln b/ExtendedJavaScriptSubset.sln similarity index 100% rename from CompilersCourseWork.sln rename to ExtendedJavaScriptSubset.sln diff --git a/Interpreter.Lib/IR/Instructions/AsString.cs b/Interpreter.Lib/BackEnd/Instructions/AsString.cs similarity index 54% rename from Interpreter.Lib/IR/Instructions/AsString.cs rename to Interpreter.Lib/BackEnd/Instructions/AsString.cs index 9a30be21..d8c9eb54 100644 --- a/Interpreter.Lib/IR/Instructions/AsString.cs +++ b/Interpreter.Lib/BackEnd/Instructions/AsString.cs @@ -1,10 +1,11 @@ +using System; using System.Collections.Generic; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using System.Diagnostics.CodeAnalysis; +using Interpreter.Lib.BackEnd.Values; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class AsString : Simple { @@ -35,5 +36,22 @@ public override int Execute(VirtualMachine vm) } protected override string ToStringRepresentation() => $"{Left} = {right.right} as string"; + + [ExcludeFromCodeCoverage] + private class DoubleValueConverter : JsonConverter + { + public override bool CanRead => false; + + public override void WriteJson(JsonWriter writer, double value, JsonSerializer serializer) => + // ReSharper disable once CompareOfFloatsByEqualityOperator + writer.WriteRawValue(value == Math.Truncate(value) + ? JsonConvert.ToString(Convert.ToInt64(value)) + : JsonConvert.ToString(value)); + + public override double ReadJson(JsonReader reader, Type objectType, + double existingValue, bool hasExistingValue, + JsonSerializer serializer) => + throw new NotImplementedException("CanRead is false, so reading is unnecessary"); + } } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Instructions/BeginFunction.cs b/Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs similarity index 86% rename from Interpreter.Lib/IR/Instructions/BeginFunction.cs rename to Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs index 5ef3a385..69da704b 100644 --- a/Interpreter.Lib/IR/Instructions/BeginFunction.cs +++ b/Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs @@ -1,6 +1,4 @@ -using Interpreter.Lib.VM; - -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class BeginFunction : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/CallFunction.cs b/Interpreter.Lib/BackEnd/Instructions/CallFunction.cs similarity index 95% rename from Interpreter.Lib/IR/Instructions/CallFunction.cs rename to Interpreter.Lib/BackEnd/Instructions/CallFunction.cs index 666b255e..dd737278 100644 --- a/Interpreter.Lib/IR/Instructions/CallFunction.cs +++ b/Interpreter.Lib/BackEnd/Instructions/CallFunction.cs @@ -1,8 +1,7 @@ using System; using System.Collections.Generic; -using Interpreter.Lib.VM; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class CallFunction : Simple { diff --git a/Interpreter.Lib/IR/Instructions/CreateArray.cs b/Interpreter.Lib/BackEnd/Instructions/CreateArray.cs similarity index 89% rename from Interpreter.Lib/IR/Instructions/CreateArray.cs rename to Interpreter.Lib/BackEnd/Instructions/CreateArray.cs index 2c0a2e7c..7f506a93 100644 --- a/Interpreter.Lib/IR/Instructions/CreateArray.cs +++ b/Interpreter.Lib/BackEnd/Instructions/CreateArray.cs @@ -1,7 +1,6 @@ using System.Linq; -using Interpreter.Lib.VM; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class CreateArray : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/CreateObject.cs b/Interpreter.Lib/BackEnd/Instructions/CreateObject.cs similarity index 88% rename from Interpreter.Lib/IR/Instructions/CreateObject.cs rename to Interpreter.Lib/BackEnd/Instructions/CreateObject.cs index 002aed5d..65e05eeb 100644 --- a/Interpreter.Lib/IR/Instructions/CreateObject.cs +++ b/Interpreter.Lib/BackEnd/Instructions/CreateObject.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; -using Interpreter.Lib.VM; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class CreateObject : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/DotAssignment.cs b/Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs similarity index 87% rename from Interpreter.Lib/IR/Instructions/DotAssignment.cs rename to Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs index 74c8d8b4..42121337 100644 --- a/Interpreter.Lib/IR/Instructions/DotAssignment.cs +++ b/Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class DotAssignment : Simple { diff --git a/Interpreter.Lib/IR/Instructions/Goto.cs b/Interpreter.Lib/BackEnd/Instructions/Goto.cs similarity index 86% rename from Interpreter.Lib/IR/Instructions/Goto.cs rename to Interpreter.Lib/BackEnd/Instructions/Goto.cs index 6881fffc..96e03b9a 100644 --- a/Interpreter.Lib/IR/Instructions/Goto.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Goto.cs @@ -1,6 +1,4 @@ -using Interpreter.Lib.VM; - -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class Goto : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/Halt.cs b/Interpreter.Lib/BackEnd/Instructions/Halt.cs similarity index 83% rename from Interpreter.Lib/IR/Instructions/Halt.cs rename to Interpreter.Lib/BackEnd/Instructions/Halt.cs index 0c160cfa..614a7a2f 100644 --- a/Interpreter.Lib/IR/Instructions/Halt.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Halt.cs @@ -1,6 +1,4 @@ -using Interpreter.Lib.VM; - -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class Halt : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/IfNotGoto.cs b/Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs similarity index 85% rename from Interpreter.Lib/IR/Instructions/IfNotGoto.cs rename to Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs index ae994416..6f275799 100644 --- a/Interpreter.Lib/IR/Instructions/IfNotGoto.cs +++ b/Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs @@ -1,8 +1,7 @@ using System; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class IfNotGoto : Goto { diff --git a/Interpreter.Lib/IR/Instructions/IndexAssignment.cs b/Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs similarity index 87% rename from Interpreter.Lib/IR/Instructions/IndexAssignment.cs rename to Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs index fe022674..3865d73e 100644 --- a/Interpreter.Lib/IR/Instructions/IndexAssignment.cs +++ b/Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class IndexAssignment : Simple { diff --git a/Interpreter.Lib/IR/Instructions/Instruction.cs b/Interpreter.Lib/BackEnd/Instructions/Instruction.cs similarity index 53% rename from Interpreter.Lib/IR/Instructions/Instruction.cs rename to Interpreter.Lib/BackEnd/Instructions/Instruction.cs index 4f126b5f..06bf49ef 100644 --- a/Interpreter.Lib/IR/Instructions/Instruction.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Instruction.cs @@ -1,35 +1,22 @@ using System; -using Interpreter.Lib.VM; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { - public abstract class Instruction : IComparable, IEquatable + public abstract class Instruction : IComparable { public int Number { get; } - public bool Leader { get; set; } - - protected Instruction(int number) - { + protected Instruction(int number) => Number = number; - } public virtual int Jump() => Number + 1; - public bool Branch() => Jump() != Number + 1; - public virtual bool End() => false; public abstract int Execute(VirtualMachine vm); public int CompareTo(Instruction other) => Number.CompareTo(other.Number); - public bool Equals(Instruction other) => other != null && Number.Equals(other.Number); - - public override bool Equals(object obj) => Equals(obj as Instruction); - - public override int GetHashCode() => Number; - protected abstract string ToStringRepresentation(); public override string ToString() => $"{Number}: {ToStringRepresentation()}"; diff --git a/Interpreter.Lib/IR/Instructions/Print.cs b/Interpreter.Lib/BackEnd/Instructions/Print.cs similarity index 69% rename from Interpreter.Lib/IR/Instructions/Print.cs rename to Interpreter.Lib/BackEnd/Instructions/Print.cs index a025bf46..934a44dd 100644 --- a/Interpreter.Lib/IR/Instructions/Print.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Print.cs @@ -1,8 +1,6 @@ -using System; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class Print : Instruction { @@ -15,7 +13,7 @@ public Print(int number, IValue value) : base(number) public override int Execute(VirtualMachine vm) { - Console.WriteLine(_value.Get(vm.Frames.Peek())); + vm.Writer.WriteLine(_value.Get(vm.Frames.Peek())); return Number + 1; } diff --git a/Interpreter.Lib/IR/Instructions/PushParameter.cs b/Interpreter.Lib/BackEnd/Instructions/PushParameter.cs similarity index 86% rename from Interpreter.Lib/IR/Instructions/PushParameter.cs rename to Interpreter.Lib/BackEnd/Instructions/PushParameter.cs index 7f8647d5..97358e4c 100644 --- a/Interpreter.Lib/IR/Instructions/PushParameter.cs +++ b/Interpreter.Lib/BackEnd/Instructions/PushParameter.cs @@ -1,7 +1,6 @@ -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class PushParameter : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/RemoveFromArray.cs b/Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs similarity index 87% rename from Interpreter.Lib/IR/Instructions/RemoveFromArray.cs rename to Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs index bceb79ba..11f65e17 100644 --- a/Interpreter.Lib/IR/Instructions/RemoveFromArray.cs +++ b/Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs @@ -1,9 +1,8 @@ using System; using System.Collections.Generic; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class RemoveFromArray : Instruction { diff --git a/Interpreter.Lib/IR/Instructions/Return.cs b/Interpreter.Lib/BackEnd/Instructions/Return.cs similarity index 91% rename from Interpreter.Lib/IR/Instructions/Return.cs rename to Interpreter.Lib/BackEnd/Instructions/Return.cs index 01de99da..b1355aaa 100644 --- a/Interpreter.Lib/IR/Instructions/Return.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Return.cs @@ -1,9 +1,8 @@ using System.Collections; using System.Collections.Generic; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class Return : Instruction, IEnumerable { diff --git a/Interpreter.Lib/IR/Instructions/Simple.cs b/Interpreter.Lib/BackEnd/Instructions/Simple.cs similarity index 76% rename from Interpreter.Lib/IR/Instructions/Simple.cs rename to Interpreter.Lib/BackEnd/Instructions/Simple.cs index cf1dbc42..d587132b 100644 --- a/Interpreter.Lib/IR/Instructions/Simple.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Simple.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.VM; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Instructions +namespace Interpreter.Lib.BackEnd.Instructions { public class Simple : Instruction { public string Left { get; set; } protected (IValue left, IValue right) right; - protected string @operator; + protected readonly string @operator; public Simple( string left, @@ -87,32 +86,6 @@ public override int Execute(VirtualMachine vm) return Jump(); } - public void ReduceToAssignment() - { - right = ToStringRepresentation().Split('=')[1].Trim() switch - { - var s - when s.EndsWith("+ 0") || s.EndsWith("- 0") || - s.EndsWith("* 1") || s.EndsWith("/ 1") => (null, right.left), - var s - when s.StartsWith("0 +") || s.StartsWith("1 *") => (null, right.right), - _ => throw new NotImplementedException() - }; - @operator = ""; - } - - public void ReduceToZero() - { - right = ToStringRepresentation().Split('=')[1].Trim() switch - { - "-0" => (null, new Constant(0, "0")), - var s - when s.EndsWith("* 0") || s.StartsWith("0 *") => (null, new Constant(0, "0")), - _ => throw new NotImplementedException() - }; - @operator = ""; - } - protected override string ToStringRepresentation() => right.left == null ? $"{Left} = {@operator}{right.right}" diff --git a/Interpreter.Lib/VM/Values/Constant.cs b/Interpreter.Lib/BackEnd/Values/Constant.cs similarity index 93% rename from Interpreter.Lib/VM/Values/Constant.cs rename to Interpreter.Lib/BackEnd/Values/Constant.cs index f11e8788..70c87341 100644 --- a/Interpreter.Lib/VM/Values/Constant.cs +++ b/Interpreter.Lib/BackEnd/Values/Constant.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.VM.Values +namespace Interpreter.Lib.BackEnd.Values { public class Constant : IValue { diff --git a/Interpreter.Lib/VM/Values/IValue.cs b/Interpreter.Lib/BackEnd/Values/IValue.cs similarity index 73% rename from Interpreter.Lib/VM/Values/IValue.cs rename to Interpreter.Lib/BackEnd/Values/IValue.cs index 2f235d1f..06255e67 100644 --- a/Interpreter.Lib/VM/Values/IValue.cs +++ b/Interpreter.Lib/BackEnd/Values/IValue.cs @@ -1,6 +1,6 @@ using System; -namespace Interpreter.Lib.VM.Values +namespace Interpreter.Lib.BackEnd.Values { public interface IValue : IEquatable { diff --git a/Interpreter.Lib/VM/Values/Name.cs b/Interpreter.Lib/BackEnd/Values/Name.cs similarity index 91% rename from Interpreter.Lib/VM/Values/Name.cs rename to Interpreter.Lib/BackEnd/Values/Name.cs index 92d643e7..7c01b685 100644 --- a/Interpreter.Lib/VM/Values/Name.cs +++ b/Interpreter.Lib/BackEnd/Values/Name.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.VM.Values +namespace Interpreter.Lib.BackEnd.Values { public class Name : IValue { diff --git a/Interpreter.Lib/BackEnd/VirtualMachine.cs b/Interpreter.Lib/BackEnd/VirtualMachine.cs new file mode 100644 index 00000000..b5ba207c --- /dev/null +++ b/Interpreter.Lib/BackEnd/VirtualMachine.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Interpreter.Lib.BackEnd.Instructions; + +namespace Interpreter.Lib.BackEnd +{ + public record VirtualMachine( + Stack CallStack, Stack Frames, + Stack<(string Id, object Value)> Arguments, + TextWriter Writer + ) + { + public VirtualMachine() : + this(new(), new(), new(), Console.Out) { } + + public void Run(List instructions) + { + Frames.Push(new Frame()); + + var address = 0; + while (!instructions[address].End()) + { + var instruction = instructions[address]; + var jump = instruction.Execute(this); + address = jump; + } + + instructions[address].Execute(this); + } + } + + public record Call( + int From, FunctionInfo To, + List<(string Id, object Value)> Parameters, + string Where = null) + { + public override string ToString() => + $"{From} => {To.Location}: {To.Id}({string.Join(", ", Parameters.Select(x => $"{x.Id}: {x.Value}"))})"; + } + + public record FunctionInfo(string Id, int Location = 0, string MethodOf = null) + { + public int Location { get; set; } = Location; + + public string MethodOf { get; set; } = MethodOf; + + public string CallId() => + MethodOf == null + ? Id + : $"{MethodOf}.{Id}"; + + public override string ToString() => + $"({Location}, {CallId()})"; + } + + public class Frame + { + private readonly Dictionary _variables = new(); + private readonly Frame _parentFrame; + + public int ReturnAddress { get; } + + public Frame(int returnAddress = 0, Frame parentFrame = null) + { + ReturnAddress = returnAddress; + _parentFrame = parentFrame; + } + + public object this[string id] + { + get => _variables.ContainsKey(id) + ? _variables[id] + : _parentFrame?[id]; + set => _variables[id] = value; + } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/DoubleValueConverter.cs b/Interpreter.Lib/DoubleValueConverter.cs deleted file mode 100644 index 877005fa..00000000 --- a/Interpreter.Lib/DoubleValueConverter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Newtonsoft.Json; - -namespace Interpreter.Lib -{ - public class DoubleValueConverter : JsonConverter - { - public override bool CanRead => false; - - public override void WriteJson(JsonWriter writer, double value, JsonSerializer serializer) - { - // ReSharper disable once CompareOfFloatsByEqualityOperator - writer.WriteRawValue(value == Math.Truncate(value) - ? JsonConvert.ToString(Convert.ToInt64(value)) - : JsonConvert.ToString(value)); - } - - public override double ReadJson(JsonReader reader, Type objectType, double existingValue, bool hasExistingValue, - JsonSerializer serializer) - { - throw new NotImplementedException("CanRead is false, so reading is unnecessary"); - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/Structure.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/Structure.cs similarity index 69% rename from Interpreter.Lib/RBNF/Analysis/Lexical/Structure.cs rename to Interpreter.Lib/FrontEnd/GetTokens/Data/Structure.cs index 87b4af61..2d451106 100644 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/Structure.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/Structure.cs @@ -1,12 +1,12 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Text.RegularExpressions; -using Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes; -using Interpreter.Lib.RBNF.Utils; +using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; -namespace Interpreter.Lib.RBNF.Analysis.Lexical +namespace Interpreter.Lib.FrontEnd.GetTokens.Data { public class Structure : IEnumerable { @@ -14,8 +14,8 @@ public Structure(List types) { types.AddRange(new List { - LexerUtils.End, - LexerUtils.Error + TokenTypeUtils.End, + TokenTypeUtils.Error }); types = types .OrderBy(t => t.Priority) @@ -39,21 +39,19 @@ public Structure(List types) public Regex Regex { get; } - public TokenType FindByTag(string tag) - { - return Types[tag]; - } + public TokenType FindByTag(string tag) => + Types[tag]; - public override string ToString() - { - return new StringBuilder() + public override string ToString() => + new StringBuilder() .AppendJoin('\n', Types.Select(x => $"{x.Key} {x.Value.Pattern}") ).ToString(); - } - - public IEnumerator GetEnumerator() => Types.Values.GetEnumerator(); + public IEnumerator GetEnumerator() => + Types.Values.GetEnumerator(); + + [ExcludeFromCodeCoverage] IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } } \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/Token.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/Token.cs new file mode 100644 index 00000000..51fabb34 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/Token.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.RegularExpressions; +using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +namespace Interpreter.Lib.FrontEnd.GetTokens.Data +{ + [ExcludeFromCodeCoverage] + public record Token(TokenType Type) + { + public Segment Segment { get; } + + public string Value { get; } + + public Token(TokenType type, Segment segment, string value) : + this(type) => + (Segment, Value) = (segment, value); + + public override string ToString() + { + var displayValue = Value; + if (displayValue != null) displayValue = Regex.Replace(Value, "\"", "\\\""); + if (Type.WhiteSpace()) displayValue = ""; + return $"{Type} {Segment}: {displayValue}"; + } + } + + [ExcludeFromCodeCoverage] + public record Segment(Coordinates Start, Coordinates End) + { + public override string ToString() => $"{Start}-{End}"; + + public static Segment operator +(Segment left, Segment right) => + new(left.Start, right.End); + } + + [ExcludeFromCodeCoverage] + public record Coordinates(int Line, int Column) + { + public Coordinates(int absolutePos, IReadOnlyList system) : + this(0, 0) + { + for (var i = 0; i < system.Count; i++) + if (absolutePos <= system[i]) + { + var offset = i == 0 ? -1 : system[i - 1]; + (Line, Column) = (i + 1, absolutePos - offset); + break; + } + + if (Line == 0) + { + (Line, Column) = (system.Count + 1, 1); + } + } + + public override string ToString() => $"({Line}, {Column})"; + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/EndOfProgramType.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/EndOfProgramType.cs new file mode 100644 index 00000000..ea457862 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/EndOfProgramType.cs @@ -0,0 +1,7 @@ +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +{ + internal record EndOfProgramType() : TokenType("EOP", "", int.MaxValue - 1) + { + public override bool EndOfProgram() => true; + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/ErrorType.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/ErrorType.cs new file mode 100644 index 00000000..199ab7c2 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/ErrorType.cs @@ -0,0 +1,7 @@ +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +{ + internal record ErrorType() : TokenType("ERROR", @"\S+", int.MaxValue) + { + public override bool Error() => true; + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenType.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenType.cs new file mode 100644 index 00000000..70337d00 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenType.cs @@ -0,0 +1,19 @@ +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +{ + public record TokenType(string Tag, string Pattern, int Priority) + { + public TokenType() : this(null, null, 0) + { + } + + public virtual bool WhiteSpace() => false; + + public virtual bool EndOfProgram() => false; + + public virtual bool Error() => false; + + public string GetNamedRegex() => $"(?<{Tag}>{Pattern})"; + + public sealed override string ToString() => Tag; + } +} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Utils/LexerUtils.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs similarity index 54% rename from Interpreter.Lib/RBNF/Utils/LexerUtils.cs rename to Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs index 9c10355e..c14bfbec 100644 --- a/Interpreter.Lib/RBNF/Utils/LexerUtils.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs @@ -1,8 +1,6 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes; - -namespace Interpreter.Lib.RBNF.Utils +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes { - public static class LexerUtils + public static class TokenTypeUtils { public static readonly TokenType End = new EndOfProgramType(); public static readonly TokenType Error = new ErrorType(); diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/WhiteSpaceType.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/WhiteSpaceType.cs new file mode 100644 index 00000000..166fcc01 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/WhiteSpaceType.cs @@ -0,0 +1,8 @@ +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +{ + public record WhiteSpaceType(string Tag = null, string Pattern = null, int Priority = 0) + : TokenType(Tag, Pattern, Priority) + { + public override bool WhiteSpace() => true; + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs b/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs new file mode 100644 index 00000000..c087a637 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.FrontEnd.GetTokens +{ + public interface ILexer + { + Structure Structure { get; } + + List GetTokens(string text); + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Impl/Lexer.cs b/Interpreter.Lib/FrontEnd/GetTokens/Impl/Lexer.cs new file mode 100644 index 00000000..6418f218 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/Impl/Lexer.cs @@ -0,0 +1,72 @@ +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.RegularExpressions; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +namespace Interpreter.Lib.FrontEnd.GetTokens.Impl +{ + public class Lexer : ILexer, IEnumerable + { + private readonly List _lines = new(); + private string _text = ""; + + public Structure Structure { get; } + + public Lexer(Structure structure) => + Structure = structure; + + public List GetTokens(string text) + { + _text = text; + + _lines.Clear(); + if (!string.IsNullOrEmpty(text)) + { + var lineMatches = + new Regex(@"(?\n)").Matches(text[^1] == '\n' + ? text + : new string(text.Append('\n').ToArray())); + foreach (Match match in lineMatches) + _lines.Add(match.Groups["NEWLINE"].Index); + } + + return this.Where(t => !t.Type.WhiteSpace()).ToList(); + } + + public IEnumerator GetEnumerator() + { + var matches = Structure.Regex.Matches(_text); + foreach (Match match in matches) + { + foreach (var type in Structure) + { + var group = match.Groups[type.Tag]; + + if (!group.Success) continue; + + var value = group.Value; + var segment = new Segment( + new Coordinates(group.Index, _lines), + new Coordinates(group.Index + group.Length, _lines) + ); + var token = new Token(type, segment, value); + + if (type.Error()) throw new LexerException(token); + + yield return token; + } + } + + yield return new Token(TokenTypeUtils.End); + } + + [ExcludeFromCodeCoverage] + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public override string ToString() => + string.Join('\n', this); + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/LexerException.cs b/Interpreter.Lib/FrontEnd/GetTokens/LexerException.cs new file mode 100644 index 00000000..60e007ac --- /dev/null +++ b/Interpreter.Lib/FrontEnd/GetTokens/LexerException.cs @@ -0,0 +1,18 @@ +using System; +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.FrontEnd.GetTokens +{ + [Serializable] + public class LexerException : Exception + { + public LexerException() { } + + protected LexerException(string message) : base(message) { } + + protected LexerException(string message, Exception inner) : base(message, inner) { } + + public LexerException(Token token) : + base($"Unknown token {token}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/TopDownParse/IParser.cs b/Interpreter.Lib/FrontEnd/TopDownParse/IParser.cs new file mode 100644 index 00000000..f91f82c3 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/TopDownParse/IParser.cs @@ -0,0 +1,9 @@ +using Interpreter.Lib.IR.Ast; + +namespace Interpreter.Lib.FrontEnd.TopDownParse +{ + public interface IParser + { + IAbstractSyntaxTree TopDownParse(string text); + } +} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Syntactic/Parser.cs b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs similarity index 91% rename from Interpreter.Lib/RBNF/Analysis/Syntactic/Parser.cs rename to Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs index bc68049c..54db4d63 100644 --- a/Interpreter.Lib/RBNF/Analysis/Syntactic/Parser.cs +++ b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs @@ -1,45 +1,40 @@ using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.RegularExpressions; -using Interpreter.Lib.RBNF.Analysis.Exceptions; -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.ComplexLiterals; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Nodes.Statements; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Expression = Interpreter.Lib.Semantic.Nodes.Expressions.Expression; - -namespace Interpreter.Lib.RBNF.Analysis.Syntactic +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.Ast; +using Interpreter.Lib.IR.Ast.Impl; +using Interpreter.Lib.IR.Ast.Nodes; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Statements; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; +using Expression = Interpreter.Lib.IR.Ast.Nodes.Expressions.Expression; + +namespace Interpreter.Lib.FrontEnd.TopDownParse.Impl { - [SuppressMessage("ReSharper", "PossibleNullReferenceException")] - public class Parser + public class Parser : IParser { - private readonly IEnumerator _tokens; - private readonly Structure _structure; + private TokensStream _tokens; + private readonly ILexer _lexer; - public Parser(Lexer lexer) - { - _tokens = lexer.Where(t => !t.Type.WhiteSpace()).GetEnumerator(); - _tokens.MoveNext(); - _structure = lexer.Structure; - } + public Parser(ILexer lexer) => + _lexer = lexer; private Token Expect(string expectedTag, string expectedValue = null) { var current = _tokens.Current; if (!CurrentIs(expectedTag)) - throw new ParserException(_tokens.Current.Segment, expectedTag, _tokens.Current); - if (_tokens.Current.Value != (expectedValue ?? _tokens.Current.Value)) + throw new ParserException(_tokens.Current!.Segment, expectedTag, _tokens.Current); + if (_tokens.Current!.Value != (expectedValue ?? _tokens.Current.Value)) throw new ParserException(_tokens.Current.Segment, expectedValue, _tokens.Current); if (CurrentIs(expectedTag) && _tokens.Current.Value == (expectedValue ?? _tokens.Current.Value)) @@ -50,20 +45,28 @@ private Token Expect(string expectedTag, string expectedValue = null) return current; } - private bool CurrentIs(string tag) => _tokens.Current.Type == _structure.FindByTag(tag); + private bool CurrentIs(string tag) => + _tokens.Current!.Type == _lexer.Structure.FindByTag(tag); - private bool CurrentIsLiteral() => CurrentIs("NullLiteral") || - CurrentIs("IntegerLiteral") || - CurrentIs("FloatLiteral") || - CurrentIs("StringLiteral") || - CurrentIs("BooleanLiteral"); + private bool CurrentIsLiteral() => + CurrentIs("NullLiteral") || + CurrentIs("IntegerLiteral") || + CurrentIs("FloatLiteral") || + CurrentIs("StringLiteral") || + CurrentIs("BooleanLiteral"); - private bool CurrentIsKeyword(string keyword) => CurrentIs("Keyword") && _tokens.Current.Value == keyword; + private bool CurrentIsKeyword(string keyword) => + CurrentIs("Keyword") && + _tokens.Current!.Value == keyword; - private bool CurrentIsOperator(string @operator) => CurrentIs("Operator") && _tokens.Current.Value == @operator; + private bool CurrentIsOperator(string @operator) => + CurrentIs("Operator") && + _tokens.Current!.Value == @operator; - public AbstractSyntaxTree TopDownParse() + public IAbstractSyntaxTree TopDownParse(string text) { + _tokens = _lexer.GetTokens(text); + var root = Script(SymbolTableUtils.GetStandardLibrary()); Expect("EOP"); return new AbstractSyntaxTree(root); @@ -351,10 +354,7 @@ private FunctionDeclaration FunctionDeclaration(SymbolTable table) var arg = Expect("Ident").Value; Expect("Colon"); var type = TypeValue(table); - args.Add(new VariableSymbol(arg) - { - Type = type - }); + args.Add(new VariableSymbol(arg, type)); } while (CurrentIs("Comma")) @@ -363,10 +363,7 @@ private FunctionDeclaration FunctionDeclaration(SymbolTable table) var arg = Expect("Ident").Value; Expect("Colon"); var type = TypeValue(table); - args.Add(new VariableSymbol(arg) - { - Type = type - }); + args.Add(new VariableSymbol(arg, type)); } Expect("RightParen"); @@ -726,7 +723,7 @@ private Expression PrimaryExpression(SymbolTable table) private Literal Literal() { - var segment = _tokens.Current.Segment; + var segment = _tokens.Current!.Segment; if (CurrentIs("StringLiteral")) { var str = Expect("StringLiteral"); @@ -785,7 +782,7 @@ private ObjectLiteral ObjectLiteral(SymbolTable table) var name = Expect("Ident").Value; Expect("Colon"); var type = TypeValue(newTable); - args.Add(new VariableSymbol(name) {Type = type}); + args.Add(new VariableSymbol(name, type)); if (!CurrentIs("RightParen")) { Expect("Comma"); diff --git a/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs new file mode 100644 index 00000000..1cde5d97 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs @@ -0,0 +1,30 @@ +using System.Collections; +using System.Collections.Generic; +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.FrontEnd.TopDownParse.Impl +{ + public class TokensStream : IEnumerator + { + private readonly IEnumerator _inner; + + private TokensStream(IEnumerator enumerator) + { + _inner = enumerator; + _inner.MoveNext(); + } + + public bool MoveNext() => _inner.MoveNext(); + + public void Reset() => _inner.Reset(); + + public Token Current => _inner.Current; + + object IEnumerator.Current => Current; + + public void Dispose() => _inner.Dispose(); + + public static implicit operator TokensStream(List tokens) => + new (tokens.GetEnumerator()); + } +} \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/TopDownParse/ParserException.cs b/Interpreter.Lib/FrontEnd/TopDownParse/ParserException.cs new file mode 100644 index 00000000..74924931 --- /dev/null +++ b/Interpreter.Lib/FrontEnd/TopDownParse/ParserException.cs @@ -0,0 +1,20 @@ +using System; +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.FrontEnd.TopDownParse +{ + [Serializable] + public class ParserException : Exception + { + public ParserException() { } + + protected ParserException(string message) : base(message) { } + + protected ParserException(string message, Exception inner) : base(message, inner) { } + + public ParserException(Segment segment, string expected, Token actual) : + base($"Wrong syntax: {segment} expected {expected}; actual = ({actual.Type.Tag}, {actual.Value})") + { + } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs b/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs new file mode 100644 index 00000000..d8482dbe --- /dev/null +++ b/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Interpreter.Lib.BackEnd.Instructions; + +namespace Interpreter.Lib.IR.Ast +{ + public interface IAbstractSyntaxTree + { + List GetInstructions(); + } +} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/AbstractSyntaxTree.cs b/Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs similarity index 81% rename from Interpreter.Lib/Semantic/AbstractSyntaxTree.cs rename to Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs index be0e1c28..d8981a38 100644 --- a/Interpreter.Lib/Semantic/AbstractSyntaxTree.cs +++ b/Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs @@ -1,14 +1,12 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Text; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Analysis; -using Interpreter.Lib.Semantic.Nodes; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.IR.Ast.Nodes; -namespace Interpreter.Lib.Semantic +namespace Interpreter.Lib.IR.Ast.Impl { - public class AbstractSyntaxTree : IDisposable + public class AbstractSyntaxTree : IAbstractSyntaxTree { private readonly AbstractSyntaxTreeNode _root; @@ -17,14 +15,16 @@ public AbstractSyntaxTree(AbstractSyntaxTreeNode root) _root = root; } - public void Check(SemanticAnalyzer analyzer) => - GetAllNodes().ToList().ForEach(analyzer.CheckCallback); + private void Check() => + GetAllNodes().ToList().ForEach(node => node.SemanticCheck()); private IEnumerable GetAllNodes() => _root.GetAllNodes(); public List GetInstructions() { + Check(); + var start = 0; var result = new List(); foreach (var node in _root) @@ -63,7 +63,5 @@ public override string ToString() }); return tree.Append("}\n").ToString(); } - - public void Dispose() => _root.SymbolTable.Dispose(); } } \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Nodes/AbstractSyntaxTreeNode.cs b/Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs similarity index 86% rename from Interpreter.Lib/Semantic/Nodes/AbstractSyntaxTreeNode.cs rename to Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs index e592d4d2..0095a5b5 100644 --- a/Interpreter.Lib/Semantic/Nodes/AbstractSyntaxTreeNode.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs @@ -1,11 +1,12 @@ using System.Collections; using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables; -namespace Interpreter.Lib.Semantic.Nodes +namespace Interpreter.Lib.IR.Ast.Nodes { public abstract class AbstractSyntaxTreeNode : IEnumerable { diff --git a/Interpreter.Lib/Semantic/Nodes/Declarations/Declaration.cs b/Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs similarity index 70% rename from Interpreter.Lib/Semantic/Nodes/Declarations/Declaration.cs rename to Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs index 67f3a15e..d96ce825 100644 --- a/Interpreter.Lib/Semantic/Nodes/Declarations/Declaration.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.Semantic.Nodes.Declarations +namespace Interpreter.Lib.IR.Ast.Nodes.Declarations { public abstract class Declaration : StatementListItem { diff --git a/Interpreter.Lib/Semantic/Nodes/Declarations/FunctionDeclaration.cs b/Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs similarity index 90% rename from Interpreter.Lib/Semantic/Nodes/Declarations/FunctionDeclaration.cs rename to Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs index 658ec819..8403d6d7 100644 --- a/Interpreter.Lib/Semantic/Nodes/Declarations/FunctionDeclaration.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Statements; -using Interpreter.Lib.Semantic.Symbols; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Statements; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.Semantic.Nodes.Declarations +namespace Interpreter.Lib.IR.Ast.Nodes.Declarations { public class FunctionDeclaration : Declaration { diff --git a/Interpreter.Lib/Semantic/Nodes/Declarations/LexicalDeclaration.cs b/Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs similarity index 86% rename from Interpreter.Lib/Semantic/Nodes/Declarations/LexicalDeclaration.cs rename to Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs index b2e1e4ab..4cb9b7e4 100644 --- a/Interpreter.Lib/Semantic/Nodes/Declarations/LexicalDeclaration.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Declarations +namespace Interpreter.Lib.IR.Ast.Nodes.Declarations { public class LexicalDeclaration : Declaration { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/AccessExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs similarity index 85% rename from Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/AccessExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs index 75644115..9b1f3dd4 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/AccessExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs @@ -1,6 +1,6 @@ -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions { public abstract class AccessExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/DotAccess.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs similarity index 80% rename from Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/DotAccess.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs index 44057010..4ba43fce 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/DotAccess.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions { public class DotAccess : AccessExpression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/IndexAccess.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs similarity index 83% rename from Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/IndexAccess.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs index 6d8f0223..9116e281 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/AccessExpressions/IndexAccess.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs @@ -1,14 +1,13 @@ using System; using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions { public class IndexAccess : AccessExpression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/AssignmentExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs similarity index 89% rename from Interpreter.Lib/Semantic/Nodes/Expressions/AssignmentExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs index 8de06831..e872c5ca 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/AssignmentExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; - -namespace Interpreter.Lib.Semantic.Nodes.Expressions +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; + +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class AssignmentExpression : Expression { @@ -64,20 +63,16 @@ internal override Type NodeCheck() var typeOfSymbol = _destinationType != null && type.Equals(TypeUtils.JavaScriptTypes.Undefined) ? _destinationType : type; - if (typeOfSymbol is ObjectType) + if (typeOfSymbol is ObjectType objectTypeOfSymbol) { - SymbolTable.AddSymbol(new ObjectSymbol(id, declaration.Const(), _source.SymbolTable, typeOfSymbol) + SymbolTable.AddSymbol(new ObjectSymbol(id, objectTypeOfSymbol, declaration.Const(), _source.SymbolTable) { - Type = typeOfSymbol, Table = _source.SymbolTable }); } else { - SymbolTable.AddSymbol(new VariableSymbol(id, declaration.Const()) - { - Type = typeOfSymbol - }); + SymbolTable.AddSymbol(new VariableSymbol(id, typeOfSymbol, declaration.Const())); } } else diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/BinaryExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs similarity index 94% rename from Interpreter.Lib/Semantic/Nodes/Expressions/BinaryExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs index d84372b9..d727d508 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/BinaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; - -namespace Interpreter.Lib.Semantic.Nodes.Expressions +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; + +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class BinaryExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/CallExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs similarity index 92% rename from Interpreter.Lib/Semantic/Nodes/Expressions/CallExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs index 53044b6a..23d17b08 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/CallExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs @@ -1,17 +1,17 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Nodes.Statements; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; - -namespace Interpreter.Lib.Semantic.Nodes.Expressions +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Statements; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; + +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class CallExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/CastAsExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs similarity index 84% rename from Interpreter.Lib/Semantic/Nodes/Expressions/CastAsExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs index 1a49870b..b2b7a433 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/CastAsExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs @@ -1,12 +1,11 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class CastAsExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs similarity index 87% rename from Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs index 149fc5ef..d9cc81d6 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.ComplexLiterals +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals { public class ArrayLiteral : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs similarity index 81% rename from Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs index 57877015..8ce598a1 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.ComplexLiterals +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals { public class ObjectLiteral : Expression { @@ -30,9 +30,9 @@ internal override Type NodeCheck() { var propType = prop.Expression.NodeCheck(); propertyTypes.Add(new PropertyType(prop.Id.Id, propType)); - prop.Id.SymbolTable.AddSymbol(propType is ObjectType - ? new ObjectSymbol(prop.Id.Id) {Type = propType, Table = prop.Expression.SymbolTable} - : new VariableSymbol(prop.Id.Id) {Type = propType} + prop.Id.SymbolTable.AddSymbol(propType is ObjectType objectType + ? new ObjectSymbol(prop.Id.Id, objectType) {Table = prop.Expression.SymbolTable} + : new VariableSymbol(prop.Id.Id, propType) ); }); _methods.ForEach(m => @@ -41,10 +41,7 @@ internal override Type NodeCheck() propertyTypes.Add(new PropertyType(symbol.Id, symbol.Type)); }); var type = new ObjectType(propertyTypes); - SymbolTable.AddSymbol(new VariableSymbol("this", true) - { - Type = type - }); + SymbolTable.AddSymbol(new VariableSymbol("this", type, true)); return type; } diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/Property.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs similarity index 84% rename from Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/Property.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs index 1be999f7..d86dd5d2 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/ComplexLiterals/Property.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.ComplexLiterals +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals { public class Property : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/ConditionalExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs similarity index 89% rename from Interpreter.Lib/Semantic/Nodes/Expressions/ConditionalExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs index 1947ce37..86d5a800 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/ConditionalExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class ConditionalExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/Expression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs similarity index 78% rename from Interpreter.Lib/Semantic/Nodes/Expressions/Expression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs index ff44b0c7..a2e6b8a8 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/Expression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; +using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.Semantic.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public abstract class Expression : AbstractSyntaxTreeNode { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/MemberExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs similarity index 82% rename from Interpreter.Lib/Semantic/Nodes/Expressions/MemberExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs index 31208752..7f1eac93 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/MemberExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.Semantic.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class MemberExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs similarity index 69% rename from Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs index 62035388..74cd8ed8 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs @@ -1,10 +1,10 @@ -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions { public class IdentifierReference : PrimaryExpression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/Literal.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs similarity index 74% rename from Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/Literal.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs index 28af43a4..7eacc3bd 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/Literal.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs @@ -1,8 +1,8 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions { public class Literal : PrimaryExpression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs similarity index 75% rename from Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs index 965e3433..59531d7e 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions { public abstract class PrimaryExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/Expressions/UnaryExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs similarity index 87% rename from Interpreter.Lib/Semantic/Nodes/Expressions/UnaryExpression.cs rename to Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs index 843b4698..f5530864 100644 --- a/Interpreter.Lib/Semantic/Nodes/Expressions/UnaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions.AccessExpressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; -using Type = Interpreter.Lib.Semantic.Types.Type; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.Semantic.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions { public class UnaryExpression : Expression { diff --git a/Interpreter.Lib/Semantic/Nodes/ScriptBody.cs b/Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs similarity index 93% rename from Interpreter.Lib/Semantic/Nodes/ScriptBody.cs rename to Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs index 6c8a294e..30b8d3f1 100644 --- a/Interpreter.Lib/Semantic/Nodes/ScriptBody.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -namespace Interpreter.Lib.Semantic.Nodes +namespace Interpreter.Lib.IR.Ast.Nodes { public class ScriptBody : AbstractSyntaxTreeNode { diff --git a/Interpreter.Lib/Semantic/Nodes/StatementListItem.cs b/Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs similarity index 82% rename from Interpreter.Lib/Semantic/Nodes/StatementListItem.cs rename to Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs index 57c01e60..ae81620f 100644 --- a/Interpreter.Lib/Semantic/Nodes/StatementListItem.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.Semantic.Nodes +namespace Interpreter.Lib.IR.Ast.Nodes { public abstract class StatementListItem : AbstractSyntaxTreeNode { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/BlockStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs similarity index 94% rename from Interpreter.Lib/Semantic/Nodes/Statements/BlockStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs index 839a472b..59f55af7 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/BlockStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; +using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class BlockStatement : Statement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/BreakStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs similarity index 77% rename from Interpreter.Lib/Semantic/Nodes/Statements/BreakStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs index 42e1eca6..25431d32 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/BreakStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; +using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class BreakStatement : InsideLoopStatement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/ContinueStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs similarity index 78% rename from Interpreter.Lib/Semantic/Nodes/Statements/ContinueStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs index 085ebfab..3fe7b118 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/ContinueStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; +using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class ContinueStatement : InsideLoopStatement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/ExpressionStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs similarity index 81% rename from Interpreter.Lib/Semantic/Nodes/Statements/ExpressionStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs index 55fb8687..be9d9a04 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/ExpressionStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Nodes.Expressions; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class ExpressionStatement : Statement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/IfStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs similarity index 90% rename from Interpreter.Lib/Semantic/Nodes/Statements/IfStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs index 8e3fd45f..d2d4694f 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/IfStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; - -namespace Interpreter.Lib.Semantic.Nodes.Statements +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class IfStatement : Statement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/InsideLoopStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs similarity index 79% rename from Interpreter.Lib/Semantic/Nodes/Statements/InsideLoopStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs index fdc7ce39..131ac296 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/InsideLoopStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs @@ -1,8 +1,8 @@ using System.Collections.Generic; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public abstract class InsideLoopStatement : Statement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/ReturnStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs similarity index 84% rename from Interpreter.Lib/Semantic/Nodes/Statements/ReturnStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs index 58c9e190..c2f5dae7 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/ReturnStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs @@ -1,16 +1,15 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class ReturnStatement : Statement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/Statement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs similarity index 70% rename from Interpreter.Lib/Semantic/Nodes/Statements/Statement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs index ea639326..79f1bdd6 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/Statement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public abstract class Statement : StatementListItem { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/TypeStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs similarity index 85% rename from Interpreter.Lib/Semantic/Nodes/Statements/TypeStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs index 81da3508..937eee38 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/TypeStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class TypeStatement : Statement { diff --git a/Interpreter.Lib/Semantic/Nodes/Statements/WhileStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs similarity index 88% rename from Interpreter.Lib/Semantic/Nodes/Statements/WhileStatement.cs rename to Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs index e82214f9..af2e4e7b 100644 --- a/Interpreter.Lib/Semantic/Nodes/Statements/WhileStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs @@ -1,14 +1,13 @@ using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; -using Interpreter.Lib.VM.Values; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements { public class WhileStatement : Statement { diff --git a/Interpreter.Lib/IR/BasicBlock.cs b/Interpreter.Lib/IR/BasicBlock.cs deleted file mode 100644 index be7f482b..00000000 --- a/Interpreter.Lib/IR/BasicBlock.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Interpreter.Lib.IR.Instructions; - -namespace Interpreter.Lib.IR -{ - public class BasicBlock : IEnumerable, IEquatable, IComparable - { - private readonly List _instructions; - - public BasicBlock(IEnumerable instructions) - { - _instructions = new List(instructions); - _instructions.Sort(); - } - - public int In() => _instructions.First().Number; - - public List Out() - { - var last = _instructions.Last(); - if (last is Return ret) - { - return ret.ToList(); - } - if (last.Branch() && (last is IfNotGoto)) - { - return new() - { - last.Jump(), - last.Number + 1 - }; - } - - return new() {last.Jump()}; - } - - public bool Equals(BasicBlock other) - { - if (other == null) - return false; - return this.Count() == other.Count() && this.Zip(other).All(pair => pair.First.Equals(pair.Second)); - } - - public IEnumerator GetEnumerator() => new List(_instructions).GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public int CompareTo(BasicBlock other) => In().CompareTo(other.In()); - - public override bool Equals(object obj) => Equals(obj as BasicBlock); - - public override int GetHashCode() => In(); - - public override string ToString() - { - var result = new StringBuilder($@"{GetHashCode()} [shape=box, label="""); - result.AppendJoin("\\n", _instructions); - return result.Append(@"""]").ToString(); - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/IR/BasicBlockBuilder.cs b/Interpreter.Lib/IR/BasicBlockBuilder.cs deleted file mode 100644 index bb9c1bd0..00000000 --- a/Interpreter.Lib/IR/BasicBlockBuilder.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Interpreter.Lib.IR.Instructions; - -namespace Interpreter.Lib.IR -{ - public class BasicBlockBuilder - { - private readonly List _instructions; - - public BasicBlockBuilder(List instructions) - { - _instructions = instructions; - } - - public List GetBasicBlocks() - { - _instructions[0].Leader = true; - - _instructions - .Where(i => i.Branch()) - .Select(i => new - { - Jump = i.Jump(), - Next = i.Number + 1 - }) - .ToList() - .ForEach(obj => - { - _instructions[obj.Jump].Leader = true; - _instructions[obj.Next].Leader = true; - }); - - var basicBlocks = new Stack(); - var instructionsInBlock = new List(); - foreach (var instruction in _instructions.AsEnumerable().Reverse()) - { - instructionsInBlock.Add(instruction); - if (instruction.Leader) - { - basicBlocks.Push(new BasicBlock(instructionsInBlock)); - instructionsInBlock.Clear(); - } - } - - return basicBlocks.ToList(); - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs new file mode 100644 index 00000000..d3e08b3e --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class ArrayAccessException : SemanticException + { + public ArrayAccessException(Segment segment, Type type) : + base(segment, $"Array element cannot be accessed with type {type} it must be of type number") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs new file mode 100644 index 00000000..6735bea0 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class AssignmentToConst : SemanticException + { + public AssignmentToConst(IdentifierReference ident) : + base(ident.Segment,$"Cannot assign to const: {ident.Id}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs new file mode 100644 index 00000000..0881f2dd --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class CannotDefineType : SemanticException + { + public CannotDefineType(Segment segment) : + base(segment, "Cannot define type") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs new file mode 100644 index 00000000..b86ec5ef --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class ConstWithoutInitializer : SemanticException + { + public ConstWithoutInitializer(IdentifierReference ident) : + base(ident.Segment, $"Const without initializer: {ident.Id}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs new file mode 100644 index 00000000..8819da8e --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class DeclarationAlreadyExists : SemanticException + { + public DeclarationAlreadyExists(IdentifierReference ident) : + base(ident.Segment, $"Declaration already exists: {ident.Id}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs new file mode 100644 index 00000000..7d1ffd9b --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class FunctionWithoutReturnStatement : SemanticException + { + public FunctionWithoutReturnStatement(Segment segment) : + base(segment, "function with non-void return type must have a return statement") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs new file mode 100644 index 00000000..248be0fc --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class IncompatibleTypesOfOperands : SemanticException + { + public IncompatibleTypesOfOperands(Segment segment, Type left, Type right) : + base(segment, $"Incompatible types of operands: {left} and {right}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs new file mode 100644 index 00000000..84d8e6f2 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class NotBooleanTestExpression : SemanticException + { + public NotBooleanTestExpression(Segment segment, Type type) : + base(segment, $"Type of expression is {type} but expected boolean") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs new file mode 100644 index 00000000..65c74162 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class ObjectAccessException : SemanticException + { + public ObjectAccessException(Segment segment, ObjectType objectType, string field) : + base(segment, $"Object type {objectType} has no field {field}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/OutsideOfLoop.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/OutsideOfLoop.cs new file mode 100644 index 00000000..3db001af --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/OutsideOfLoop.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class OutsideOfLoop : SemanticException + { + public OutsideOfLoop(Segment segment, string keyword) : + base(segment, $"\"{keyword}\" outside of loop") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs new file mode 100644 index 00000000..20d67a72 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class ReturnOutsideFunction : SemanticException + { + public ReturnOutsideFunction(Segment segment) : + base(segment, "\"return\" outside function") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs new file mode 100644 index 00000000..36d9b978 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs @@ -0,0 +1,18 @@ +using System; +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + [Serializable] + public abstract class SemanticException : Exception + { + protected SemanticException() { } + + protected SemanticException(string message) : base(message) { } + + protected SemanticException(string message, Exception inner) : base(message, inner) { } + + protected SemanticException(Segment segment, string message) : + base($"{segment} {message}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs new file mode 100644 index 00000000..2fae5f0d --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class SymbolIsNotCallable: SemanticException + { + public SymbolIsNotCallable(string symbol, Segment segment) : + base(segment, $"Symbol is not callable: {symbol}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs new file mode 100644 index 00000000..4aa9862a --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class UnknownIdentifierReference : SemanticException + { + public UnknownIdentifierReference(IdentifierReference ident) : + base(ident.Segment, $"Unknown identifier reference: {ident.Id}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs new file mode 100644 index 00000000..a875e1f6 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class UnsupportedOperation : SemanticException + { + public UnsupportedOperation(Segment segment, Type type, string @operator) : + base(segment, $"Type {type} does not support operation {@operator}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs new file mode 100644 index 00000000..4386f41e --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class WrongArrayLiteralDeclaration : SemanticException + { + public WrongArrayLiteralDeclaration(Segment segment, Type type) : + base(segment, $"{segment} Wrong array literal declaration: all array elements must be of type {type}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs new file mode 100644 index 00000000..6ea3a806 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class WrongConditionalTypes : SemanticException + { + public WrongConditionalTypes(Segment cSegment, Type cType, Segment aSegment, Type aType) : + base(cSegment + aSegment, $"Different types in conditional: {cSegment} consequent - {cType}, {aSegment} alternate {aType}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs new file mode 100644 index 00000000..490991a9 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs @@ -0,0 +1,10 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class WrongNumberOfArguments : SemanticException + { + public WrongNumberOfArguments(Segment segment, int expected, int actual) : + base(segment, $"Wrong number of arguments: expected {expected}, actual {actual}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs new file mode 100644 index 00000000..617516b5 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class WrongReturnType : SemanticException + { + public WrongReturnType(Segment segment, Type expected, Type actual) : + base(segment, $"Wrong return type: expected {expected}, actual {actual}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs new file mode 100644 index 00000000..da00ce69 --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs @@ -0,0 +1,11 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +{ + public class WrongTypeOfArgument : SemanticException + { + public WrongTypeOfArgument(Segment segment, Type expected, Type actual) : + base(segment,$"Wrong type of argument: expected {expected}, actual {actual}") { } + } +} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Types/Any.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Any.cs similarity index 81% rename from Interpreter.Lib/Semantic/Types/Any.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/Any.cs index a10eef4b..cefb8955 100644 --- a/Interpreter.Lib/Semantic/Types/Any.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Any.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class Any : Type { diff --git a/Interpreter.Lib/Semantic/Types/ArrayType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs similarity index 89% rename from Interpreter.Lib/Semantic/Types/ArrayType.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs index 5038a7ae..b3d8210a 100644 --- a/Interpreter.Lib/Semantic/Types/ArrayType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs @@ -1,7 +1,7 @@ -using Interpreter.Lib.Semantic.Types.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class ArrayType : Type { diff --git a/Interpreter.Lib/Semantic/Types/FunctionType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs similarity index 94% rename from Interpreter.Lib/Semantic/Types/FunctionType.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs index 669225c1..8989ce99 100644 --- a/Interpreter.Lib/Semantic/Types/FunctionType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs @@ -2,10 +2,10 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Interpreter.Lib.Semantic.Types.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class FunctionType : Type { diff --git a/Interpreter.Lib/Semantic/Types/NullType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs similarity index 86% rename from Interpreter.Lib/Semantic/Types/NullType.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs index 2d3e3ce5..c5712b55 100644 --- a/Interpreter.Lib/Semantic/Types/NullType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs @@ -1,4 +1,4 @@ -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class NullType : Type { diff --git a/Interpreter.Lib/Semantic/Types/NullableType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs similarity index 89% rename from Interpreter.Lib/Semantic/Types/NullableType.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs index 28d21f0b..89b1ad88 100644 --- a/Interpreter.Lib/Semantic/Types/NullableType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs @@ -1,7 +1,7 @@ -using Interpreter.Lib.Semantic.Types.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class NullableType : Type { diff --git a/Interpreter.Lib/Semantic/Types/ObjectType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs similarity index 95% rename from Interpreter.Lib/Semantic/Types/ObjectType.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs index ff37c8aa..1f08bb81 100644 --- a/Interpreter.Lib/Semantic/Types/ObjectType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.Semantic.Types.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class ObjectType : NullableType { diff --git a/Interpreter.Lib/Semantic/Types/Type.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Type.cs similarity index 91% rename from Interpreter.Lib/Semantic/Types/Type.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/Type.cs index da5924b2..74c10b5d 100644 --- a/Interpreter.Lib/Semantic/Types/Type.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Type.cs @@ -1,7 +1,7 @@ -using Interpreter.Lib.Semantic.Types.Visitors; +using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types { public class Type : IVisitable, diff --git a/Interpreter.Lib/Semantic/Utils/TypeUtils.cs b/Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs similarity index 94% rename from Interpreter.Lib/Semantic/Utils/TypeUtils.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs index 2d3f3874..75162cac 100644 --- a/Interpreter.Lib/Semantic/Utils/TypeUtils.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; -using Interpreter.Lib.Semantic.Types; -namespace Interpreter.Lib.Semantic.Utils +namespace Interpreter.Lib.IR.CheckSemantics.Types { public static class TypeUtils { diff --git a/Interpreter.Lib/Semantic/Types/Visitors/ObjectTypePrinter.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs similarity index 97% rename from Interpreter.Lib/Semantic/Types/Visitors/ObjectTypePrinter.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs index 48f66105..5c55ebc1 100644 --- a/Interpreter.Lib/Semantic/Types/Visitors/ObjectTypePrinter.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs @@ -2,7 +2,7 @@ using System.Text; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types.Visitors +namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors { public class ObjectTypePrinter : IVisitor, diff --git a/Interpreter.Lib/Semantic/Types/Visitors/ReferenceResolver.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs similarity index 97% rename from Interpreter.Lib/Semantic/Types/Visitors/ReferenceResolver.cs rename to Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs index 6c21650e..7d50ba7e 100644 --- a/Interpreter.Lib/Semantic/Types/Visitors/ReferenceResolver.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs @@ -1,6 +1,6 @@ using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.Semantic.Types.Visitors +namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors { public class ReferenceResolver : IVisitor, diff --git a/Interpreter.Lib/Semantic/SymbolTable.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs similarity index 63% rename from Interpreter.Lib/Semantic/SymbolTable.cs rename to Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs index a8265bbb..8b79e860 100644 --- a/Interpreter.Lib/Semantic/SymbolTable.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs @@ -1,23 +1,19 @@ -using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using Interpreter.Lib.Semantic.Symbols; -using Type = Interpreter.Lib.Semantic.Types.Type; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.Semantic +namespace Interpreter.Lib.IR.CheckSemantics.Variables { - public class SymbolTable : IDisposable + public class SymbolTable { private readonly Dictionary _symbols = new(); private readonly Dictionary _types = new(); private SymbolTable _openScope; - private readonly List _subScopes = new(); public void AddOpenScope(SymbolTable table) { _openScope = table; - table._subScopes.Add(this); } public void AddSymbol(Symbol symbol) => _symbols[symbol.Id] = symbol; @@ -46,26 +42,5 @@ public T FindSymbol(string id) where T : Symbol public bool ContainsSymbol(string id) => _symbols.ContainsKey(id); public void Clear() => _symbols.Clear(); - - private void DeepClean() - { - Clear(); - foreach (var child in _subScopes) - { - child.DeepClean(); - } - } - - [SuppressMessage("ReSharper", "CA1816")] - public void Dispose() - { - var table = _openScope; - while (table._openScope != null) - { - table = table._openScope; - } - - table.DeepClean(); - } } } \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Utils/SymbolTableUtils.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs similarity index 75% rename from Interpreter.Lib/Semantic/Utils/SymbolTableUtils.cs rename to Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs index 8e80e37f..97e42065 100644 --- a/Interpreter.Lib/Semantic/Utils/SymbolTableUtils.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs @@ -1,12 +1,12 @@ using System.Collections.Generic; -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Nodes; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Nodes.Statements; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.IR.Ast.Nodes; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.Ast.Nodes.Statements; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.Semantic.Utils +namespace Interpreter.Lib.IR.CheckSemantics.Variables { public static class SymbolTableUtils { @@ -24,10 +24,7 @@ public static SymbolTable GetStandardLibrary() "print", new List { - new VariableSymbol("str") - { - Type = TypeUtils.JavaScriptTypes.String - } + new VariableSymbol("str", TypeUtils.JavaScriptTypes.String) }, new FunctionType(TypeUtils.JavaScriptTypes.Void, new[] {TypeUtils.JavaScriptTypes.String}) ); diff --git a/Interpreter.Lib/Semantic/Symbols/FunctionSymbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs similarity index 71% rename from Interpreter.Lib/Semantic/Symbols/FunctionSymbol.cs rename to Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs index 9dbe9e83..1cc2f38c 100644 --- a/Interpreter.Lib/Semantic/Symbols/FunctionSymbol.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs @@ -1,14 +1,14 @@ using System.Collections.Generic; using System.Text; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.VM; +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Symbols +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols { public class FunctionSymbol : Symbol { - public FunctionType Type { get; } + public override FunctionType Type { get; } public List Parameters { get; } @@ -16,7 +16,8 @@ public class FunctionSymbol : Symbol public FunctionInfo CallInfo { get; } - public FunctionSymbol(string id, IEnumerable parameters, FunctionType type) : base(id) + public FunctionSymbol(string id, IEnumerable parameters, FunctionType type) : + base(id, type) { Parameters = new List(parameters); CallInfo = new FunctionInfo(id); diff --git a/Interpreter.Lib/Semantic/Symbols/ObjectSymbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs similarity index 55% rename from Interpreter.Lib/Semantic/Symbols/ObjectSymbol.cs rename to Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs index 04dbd21b..5f3906d3 100644 --- a/Interpreter.Lib/Semantic/Symbols/ObjectSymbol.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs @@ -1,12 +1,18 @@ -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.Semantic.Symbols +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols { public class ObjectSymbol : VariableSymbol { - public ObjectSymbol(string id, bool readOnly = false, SymbolTable table = null, Type type = null) : base(id, readOnly) + public override ObjectType Type { get; } + + public SymbolTable Table { get; init; } + + public ObjectSymbol(string id, ObjectType objectType, bool readOnly = false, SymbolTable table = null) : + base(id, objectType, readOnly) { - if (table != null && type is ObjectType objectType) + Type = objectType; + if (table != null) { foreach (var key in objectType.Keys) { @@ -18,7 +24,5 @@ public ObjectSymbol(string id, bool readOnly = false, SymbolTable table = null, } } } - - public SymbolTable Table { get; init; } } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs new file mode 100644 index 00000000..8a14e05a --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs @@ -0,0 +1,15 @@ +using Interpreter.Lib.IR.CheckSemantics.Types; + +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols +{ + public abstract class Symbol + { + // ReSharper disable once VirtualMemberNeverOverridden.Global + public virtual string Id { get; } + + public virtual Type Type { get; } + + protected Symbol(string id, Type type) => + (Id, Type) = (id, type); + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/VariableSymbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/VariableSymbol.cs new file mode 100644 index 00000000..37e29f0e --- /dev/null +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/VariableSymbol.cs @@ -0,0 +1,15 @@ +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; + +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols +{ + public class VariableSymbol : Symbol + { + public bool ReadOnly { get; } + + public VariableSymbol(string id, Type type, bool readOnly = false) : + base(id, type) => + ReadOnly = readOnly; + + public override string ToString() => $"{(ReadOnly ? "const " : "")}{Id}: {Type}"; + } +} \ No newline at end of file diff --git a/Interpreter.Lib/IR/ControlFlowGraph.cs b/Interpreter.Lib/IR/ControlFlowGraph.cs deleted file mode 100644 index 3e923fd0..00000000 --- a/Interpreter.Lib/IR/ControlFlowGraph.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.IR.Optimizers; - -namespace Interpreter.Lib.IR -{ - public class ControlFlowGraph - { - private readonly Dictionary> _adjacencyList = new(); - - public ControlFlowGraph(List basicBlocks) - { - basicBlocks.ForEach(basicBlock => - _adjacencyList[basicBlock] = basicBlocks - .Where(bb => basicBlock.Out().Contains(bb.In())) - .ToList() - ); - } - - public BasicBlock Entry => _adjacencyList.Keys.Min(); - - public BasicBlock NextBlock(BasicBlock current, int jump) => - _adjacencyList[current] - .FirstOrDefault(bb => bb.In() == jump); - - public void OptimizeInstructions(params Func>[] generators) - { - foreach (var bb in _adjacencyList.Keys) - { - foreach (var instruction in bb) - { - foreach (var generator in generators) - { - var optimizer = generator(null); - if (optimizer.CanOptimize(instruction)) - { - optimizer = generator(instruction); - optimizer.Optimize(); - } - } - } - } - } - - public override string ToString() - { - var result = new StringBuilder("digraph cfg {\n"); - foreach (var basicBlock in _adjacencyList.Keys) - { - result.Append($"\t{basicBlock}\n"); - foreach (var bb in _adjacencyList[basicBlock]) - { - result.Append($"\t{basicBlock.GetHashCode()}->{bb.GetHashCode()}\n"); - } - } - - return result.Append('}').ToString(); - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/IR/Optimizers/IOptimizer.cs b/Interpreter.Lib/IR/Optimizers/IOptimizer.cs deleted file mode 100644 index 8c699cda..00000000 --- a/Interpreter.Lib/IR/Optimizers/IOptimizer.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Interpreter.Lib.IR.Instructions; - -namespace Interpreter.Lib.IR.Optimizers -{ - public interface IOptimizer where T : Instruction - { - T Instruction { get; } - - bool Test(); - - void Optimize(); - - bool CanOptimize(Instruction instruction) => - typeof(T) == instruction.GetType(); - } -} \ No newline at end of file diff --git a/Interpreter.Lib/IR/Optimizers/IdentityExpression.cs b/Interpreter.Lib/IR/Optimizers/IdentityExpression.cs deleted file mode 100644 index ad0d8bda..00000000 --- a/Interpreter.Lib/IR/Optimizers/IdentityExpression.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Interpreter.Lib.IR.Instructions; - -namespace Interpreter.Lib.IR.Optimizers -{ - public class IdentityExpression : IOptimizer - { - public Simple Instruction { get; } - - public IdentityExpression(Simple instruction) - { - Instruction = instruction; - } - - public bool Test() - { - var s = Instruction.ToString().Split('=')[1].Trim(); - return s.EndsWith("+ 0") || s.StartsWith("0 +") || - s.EndsWith("* 1") || s.StartsWith("1 *") || - s.EndsWith("- 0") || s.EndsWith("/ 1"); - } - - public void Optimize() - { - if (Test()) - { - Instruction.ReduceToAssignment(); - } - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/IR/Optimizers/ZeroExpression.cs b/Interpreter.Lib/IR/Optimizers/ZeroExpression.cs deleted file mode 100644 index ab5b4654..00000000 --- a/Interpreter.Lib/IR/Optimizers/ZeroExpression.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Interpreter.Lib.IR.Instructions; - -namespace Interpreter.Lib.IR.Optimizers -{ - public class ZeroExpression : IOptimizer - { - public Simple Instruction { get; } - - public ZeroExpression(Simple instruction) - { - Instruction = instruction; - } - - public bool Test() - { - var s = Instruction.ToString().Split('=')[1].Trim(); - return s == "-0" || - s.EndsWith("* 0") || s.StartsWith("0 *"); - } - - public void Optimize() - { - if (Test()) - { - Instruction.ReduceToZero(); - } - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Interpreter.Lib.csproj b/Interpreter.Lib/Interpreter.Lib.csproj index 02de8607..54610ed4 100644 --- a/Interpreter.Lib/Interpreter.Lib.csproj +++ b/Interpreter.Lib/Interpreter.Lib.csproj @@ -1,13 +1,9 @@ - net5.0 + net6.0 - - - - diff --git a/Interpreter.Lib/RBNF/Analysis/Exceptions/LexerException.cs b/Interpreter.Lib/RBNF/Analysis/Exceptions/LexerException.cs deleted file mode 100644 index 0e0862b4..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Exceptions/LexerException.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System; -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.RBNF.Analysis.Exceptions -{ - public class LexerException : Exception - { - public LexerException(Token token) : base($"Unknown token {token}") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Exceptions/ParserException.cs b/Interpreter.Lib/RBNF/Analysis/Exceptions/ParserException.cs deleted file mode 100644 index 4bd3c94a..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Exceptions/ParserException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.RBNF.Analysis.Exceptions -{ - public class ParserException : Exception - { - public ParserException(Segment segment, string expected, Token actual) : - base($"Wrong syntax: {segment} expected {expected}; actual = ({actual.Type.Tag}, {actual.Value})") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/Coordinates.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/Coordinates.cs deleted file mode 100644 index 7f1ffcf5..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/Coordinates.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Interpreter.Lib.RBNF.Analysis.Lexical -{ - public class Coordinates : IEquatable - { - [JsonProperty] private readonly int _line, _column; - - public Coordinates(int line, int column) - { - (_line, _column) = (line, column); - } - - public Coordinates(int absolutePos, List system) - { - for (var i = 0; i < system.Count; i++) - if (absolutePos <= system[i]) - { - var offset = i == 0 ? -1 : system[i - 1]; - _line = i + 1; - _column = absolutePos - offset; - break; - } - - if (_line == 0) - { - _column = 1; - _line = system.Count + 1; - } - } - - public override string ToString() - { - return $"({_line}, {_column})"; - } - - public override bool Equals(object obj) => Equals(obj as Coordinates); - - public override int GetHashCode() => HashCode.Combine(_line, _column); - - public bool Equals(Coordinates obj) - { - if (ReferenceEquals(null, obj)) return false; - return _line == obj._line && _column == obj._column; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/Lexer.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/Lexer.cs deleted file mode 100644 index 4b849f68..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/Lexer.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text.RegularExpressions; -using Interpreter.Lib.RBNF.Analysis.Exceptions; -using Interpreter.Lib.RBNF.Utils; - -namespace Interpreter.Lib.RBNF.Analysis.Lexical -{ - public class Lexer : IEnumerable - { - private readonly List _lines = new(); - private readonly string _source; - - public Structure Structure { get; } - - public Lexer(Structure structure, string source) - { - Structure = structure; - _source = source; - - var lineMatches = - new Regex(@"(?\n)").Matches(source[^1] == '\n' - ? source - : new string(source.Append('\n').ToArray())); - foreach (Match match in lineMatches) _lines.Add(match.Groups["NEWLINE"].Index); - } - - public IEnumerator GetEnumerator() - { - var matches = Structure.Regex.Matches(_source); - foreach (Match match in matches) - { - foreach (var type in Structure) - { - var group = match.Groups[type.Tag]; - - if (!group.Success) continue; - - var value = group.Value; - var segment = new Segment( - new Coordinates(group.Index, _lines), - new Coordinates(group.Index + group.Length, _lines) - ); - var token = new Token(type, segment, value); - - if (type == LexerUtils.Error) throw new LexerException(token); - - yield return token; - } - } - - yield return new Token(LexerUtils.End); - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/Segment.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/Segment.cs deleted file mode 100644 index 66a5ac23..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/Segment.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using Newtonsoft.Json; - -namespace Interpreter.Lib.RBNF.Analysis.Lexical -{ - public class Segment : IEquatable - { - [JsonProperty] private readonly Coordinates _start, _end; - - public Segment(Coordinates start, Coordinates end) - { - (_start, _end) = (start, end); - } - - public override string ToString() - { - return $"{_start}-{_end}"; - } - - public override bool Equals(object obj) => Equals(obj as Segment); - - public override int GetHashCode() => HashCode.Combine(_start, _end); - - public bool Equals(Segment obj) - { - if (ReferenceEquals(null, obj)) return false; - return Equals(_start, obj._start) && Equals(_end, obj._end); - } - - public static Segment operator +(Segment left, Segment right) => - new(left._start, right._end); - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/Token.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/Token.cs deleted file mode 100644 index 86764403..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/Token.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Text.RegularExpressions; -using Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes; - -namespace Interpreter.Lib.RBNF.Analysis.Lexical -{ - public class Token : ICloneable, IEquatable - { - public Segment Segment { get; } - - public Token(TokenType type) - { - Type = type; - } - - public Token(TokenType type, Segment segment, string value) : this(type) - { - (Segment, Value) = (segment, value); - } - - public TokenType Type { get; } - - public string Value { get; } - - public override string ToString() - { - var displayValue = Value; - if (displayValue != null) displayValue = Regex.Replace(Value, "\"", "\\\""); - if (Type.WhiteSpace()) displayValue = ""; - return $"{Type} {Segment}: {displayValue}"; - } - - public object Clone() - { - return new Token(Type, Segment, Value); - } - - public override bool Equals(object obj) => Equals(obj as Token); - - public override int GetHashCode() => HashCode.Combine(Type, Segment, Value); - - public bool Equals(Token obj) - { - if (ReferenceEquals(null, obj)) return false; - return Type == obj.Type && Equals(Segment, obj.Segment) && Value == obj.Value; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/EndOfProgramType.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/EndOfProgramType.cs deleted file mode 100644 index b7789c03..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/EndOfProgramType.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes -{ - internal record EndOfProgramType : TokenType - { - public EndOfProgramType() : base("EOP", "", int.MaxValue - 1) - { - } - - public override bool EndOfProgram() - { - return true; - } - - public override string ToString() - { - return Tag; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/ErrorType.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/ErrorType.cs deleted file mode 100644 index 01122113..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/ErrorType.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes -{ - internal record ErrorType : TokenType - { - public ErrorType() : base("ERROR", @"\S+", int.MaxValue) - { - } - - public override bool Error() - { - return true; - } - - public override string ToString() - { - return Tag; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/TokenType.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/TokenType.cs deleted file mode 100644 index b16e2874..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/TokenType.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes -{ - public record TokenType(string Tag, string Pattern, int Priority) - { - public TokenType() : this(null, null, 0) - { - } - - public virtual bool WhiteSpace() - { - return false; - } - - public virtual bool EndOfProgram() - { - return false; - } - - public virtual bool Error() - { - return false; - } - - public virtual bool NonTerminal() - { - return false; - } - - public virtual bool Terminal() - { - return false; - } - - public virtual bool Epsilon() - { - return false; - } - - public string GetNamedRegex() - { - return $"(?<{Tag}>{Pattern})"; - } - - public override string ToString() - { - return Tag; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/WhiteSpaceType.cs b/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/WhiteSpaceType.cs deleted file mode 100644 index c67f1962..00000000 --- a/Interpreter.Lib/RBNF/Analysis/Lexical/TokenTypes/WhiteSpaceType.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes -{ - public record WhiteSpaceType(string Tag = null, string Pattern = null, int Priority = 0) - : TokenType(Tag, Pattern, Priority) - { - public override bool WhiteSpace() - { - return true; - } - - public override string ToString() - { - return Tag; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Analysis/SemanticAnalyzer.cs b/Interpreter.Lib/Semantic/Analysis/SemanticAnalyzer.cs deleted file mode 100644 index 3f4d14ca..00000000 --- a/Interpreter.Lib/Semantic/Analysis/SemanticAnalyzer.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using Interpreter.Lib.Semantic.Nodes; - -namespace Interpreter.Lib.Semantic.Analysis -{ - public class SemanticAnalyzer - { - public Action CheckCallback { get; } - - public SemanticAnalyzer(Action checkCallback) - { - CheckCallback = checkCallback; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/ArrayAccessException.cs b/Interpreter.Lib/Semantic/Exceptions/ArrayAccessException.cs deleted file mode 100644 index d3a27b40..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/ArrayAccessException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class ArrayAccessException : SemanticException - { - public ArrayAccessException(Segment segment, Type type) : - base($"{segment} Array element cannot be accessed with type {type} it must be of type number") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/AssignmentToConst.cs b/Interpreter.Lib/Semantic/Exceptions/AssignmentToConst.cs deleted file mode 100644 index 9d792e1e..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/AssignmentToConst.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class AssignmentToConst : SemanticException - { - public AssignmentToConst(IdentifierReference ident) : - base( - $"{ident.Segment} Cannot assign to const: {ident.Id}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/CannotDefineType.cs b/Interpreter.Lib/Semantic/Exceptions/CannotDefineType.cs deleted file mode 100644 index e1f49035..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/CannotDefineType.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class CannotDefineType : SemanticException - { - public CannotDefineType(Segment segment) : - base($"{segment} Cannot define type") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/ConstWithoutInitializer.cs b/Interpreter.Lib/Semantic/Exceptions/ConstWithoutInitializer.cs deleted file mode 100644 index 7733e26e..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/ConstWithoutInitializer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class ConstWithoutInitializer : SemanticException - { - public ConstWithoutInitializer(IdentifierReference ident) : base($"{ident.Segment} Const without initializer: {ident.Id}") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/DeclarationAlreadyExists.cs b/Interpreter.Lib/Semantic/Exceptions/DeclarationAlreadyExists.cs deleted file mode 100644 index 7c7cb621..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/DeclarationAlreadyExists.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class DeclarationAlreadyExists : SemanticException - { - public DeclarationAlreadyExists(IdentifierReference ident) : base($"{ident.Segment} Declaration already exists: {ident.Id}") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/FunctionWithoutReturnStatement.cs b/Interpreter.Lib/Semantic/Exceptions/FunctionWithoutReturnStatement.cs deleted file mode 100644 index e07ad959..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/FunctionWithoutReturnStatement.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class FunctionWithoutReturnStatement : SemanticException - { - public FunctionWithoutReturnStatement(Segment segment) : - base( - $"{segment} function with non-void return type must have a return statement" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/IncompatibleTypesOfOperands.cs b/Interpreter.Lib/Semantic/Exceptions/IncompatibleTypesOfOperands.cs deleted file mode 100644 index f3eec819..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/IncompatibleTypesOfOperands.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class IncompatibleTypesOfOperands : SemanticException - { - public IncompatibleTypesOfOperands(Segment segment, Type left, Type right) : - base( - $"{segment} Incompatible types of operands: {left} and {right}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/NotBooleanTestExpression.cs b/Interpreter.Lib/Semantic/Exceptions/NotBooleanTestExpression.cs deleted file mode 100644 index add04790..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/NotBooleanTestExpression.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class NotBooleanTestExpression : SemanticException - { - public NotBooleanTestExpression(Segment segment, Type type) : - base( - $"{segment} Type of expression is {type} but expected boolean" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/ObjectAccessException.cs b/Interpreter.Lib/Semantic/Exceptions/ObjectAccessException.cs deleted file mode 100644 index ab41d605..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/ObjectAccessException.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class ObjectAccessException : SemanticException - { - public ObjectAccessException(Segment segment, ObjectType objectType, string field) : - base($"{segment} Object type {objectType} has no field {field}") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/OutsideOfLoop.cs b/Interpreter.Lib/Semantic/Exceptions/OutsideOfLoop.cs deleted file mode 100644 index 86fcedb7..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/OutsideOfLoop.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class OutsideOfLoop : SemanticException - { - public OutsideOfLoop(Segment segment, string keyword) : - base( - $"{segment} \"{keyword}\" outside of loop" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/ReturnOutsideFunction.cs b/Interpreter.Lib/Semantic/Exceptions/ReturnOutsideFunction.cs deleted file mode 100644 index 8bcdbece..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/ReturnOutsideFunction.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class ReturnOutsideFunction : SemanticException - { - public ReturnOutsideFunction(Segment segment) : - base( - $"{segment} \"return\" outside function" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/SemanticException.cs b/Interpreter.Lib/Semantic/Exceptions/SemanticException.cs deleted file mode 100644 index 34c94a87..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/SemanticException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public abstract class SemanticException : Exception - { - protected SemanticException(string message) : base(message) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/SymbolIsNotCallable.cs b/Interpreter.Lib/Semantic/Exceptions/SymbolIsNotCallable.cs deleted file mode 100644 index 6406b134..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/SymbolIsNotCallable.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class SymbolIsNotCallable: SemanticException - { - public SymbolIsNotCallable(string symbol, Segment segment) : - base($"{segment} Symbol is not callable: {symbol}") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/UnknownIdentifierReference.cs b/Interpreter.Lib/Semantic/Exceptions/UnknownIdentifierReference.cs deleted file mode 100644 index a7d1e65a..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/UnknownIdentifierReference.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class UnknownIdentifierReference : SemanticException - { - public UnknownIdentifierReference(IdentifierReference ident) : - base( - $"{ident.Segment} Unknown identifier reference: {ident.Id}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/UnsupportedOperation.cs b/Interpreter.Lib/Semantic/Exceptions/UnsupportedOperation.cs deleted file mode 100644 index 263e12b9..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/UnsupportedOperation.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class UnsupportedOperation : SemanticException - { - public UnsupportedOperation(Segment segment, Type type, string @operator) : - base( - $"{segment} Type {type} does not support operation {@operator}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/WrongArrayLiteralDeclaration.cs b/Interpreter.Lib/Semantic/Exceptions/WrongArrayLiteralDeclaration.cs deleted file mode 100644 index 889647c5..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/WrongArrayLiteralDeclaration.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class WrongArrayLiteralDeclaration : SemanticException - { - public WrongArrayLiteralDeclaration(Segment segment, Type type) : - base($"{segment} Wrong array literal declaration: all array elements must be of type {type}") - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/WrongConditionalTypes.cs b/Interpreter.Lib/Semantic/Exceptions/WrongConditionalTypes.cs deleted file mode 100644 index 6ff31488..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/WrongConditionalTypes.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class WrongConditionalTypes : SemanticException - { - public WrongConditionalTypes(Segment cSegment, Type cType, Segment aSegment, Type aType) : - base( - $"Different types in conditional: {cSegment} consequent - {cType}, {aSegment} alternate {aType}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/WrongNumberOfArguments.cs b/Interpreter.Lib/Semantic/Exceptions/WrongNumberOfArguments.cs deleted file mode 100644 index 39b35b50..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/WrongNumberOfArguments.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class WrongNumberOfArguments : SemanticException - { - public WrongNumberOfArguments(Segment segment, int expected, int actual) : - base( - $"{segment} Wrong number of arguments: expected {expected}, actual {actual}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/WrongReturnType.cs b/Interpreter.Lib/Semantic/Exceptions/WrongReturnType.cs deleted file mode 100644 index 2311a5e4..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/WrongReturnType.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class WrongReturnType : SemanticException - { - public WrongReturnType(Segment segment, Type expected, Type actual) : - base( - $"{segment} Wrong return type: expected {expected}, actual {actual}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Exceptions/WrongTypeOfArgument.cs b/Interpreter.Lib/Semantic/Exceptions/WrongTypeOfArgument.cs deleted file mode 100644 index 25c95d45..00000000 --- a/Interpreter.Lib/Semantic/Exceptions/WrongTypeOfArgument.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.Semantic.Types; - -namespace Interpreter.Lib.Semantic.Exceptions -{ - public class WrongTypeOfArgument : SemanticException - { - public WrongTypeOfArgument(Segment segment, Type expected, Type actual) : - base( - $"{segment} Wrong type of argument: expected {expected}, actual {actual}" - ) - { - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Symbols/Symbol.cs b/Interpreter.Lib/Semantic/Symbols/Symbol.cs deleted file mode 100644 index 3f696fbf..00000000 --- a/Interpreter.Lib/Semantic/Symbols/Symbol.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Interpreter.Lib.Semantic.Symbols -{ - public abstract class Symbol - { - // ReSharper disable once VirtualMemberNeverOverridden.Global - public virtual string Id { get; } - - protected Symbol(string id) - { - Id = id; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/Semantic/Symbols/VariableSymbol.cs b/Interpreter.Lib/Semantic/Symbols/VariableSymbol.cs deleted file mode 100644 index 973ab198..00000000 --- a/Interpreter.Lib/Semantic/Symbols/VariableSymbol.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Type = Interpreter.Lib.Semantic.Types.Type; - -namespace Interpreter.Lib.Semantic.Symbols -{ - public class VariableSymbol : Symbol - { - public Type Type { get; init; } - - public bool ReadOnly { get; } - - public VariableSymbol(string id, bool readOnly = false) : base(id) - { - ReadOnly = readOnly; - } - - public override string ToString() => $"{(ReadOnly ? "const " : "")}{Id}: {Type}"; - } -} \ No newline at end of file diff --git a/Interpreter.Lib/VM/Call.cs b/Interpreter.Lib/VM/Call.cs deleted file mode 100644 index 162591ab..00000000 --- a/Interpreter.Lib/VM/Call.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -namespace Interpreter.Lib.VM -{ - public record Call( - int From, FunctionInfo To, - List<(string Id, object Value)> Parameters, - string Where = null) - { - public override string ToString() => - $"{From} => {To.Location}: {To.Id}({string.Join(", ", Parameters.Select(x => $"{x.Id}: {x.Value}"))})"; - } -} \ No newline at end of file diff --git a/Interpreter.Lib/VM/Frame.cs b/Interpreter.Lib/VM/Frame.cs deleted file mode 100644 index 389e5a52..00000000 --- a/Interpreter.Lib/VM/Frame.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System.Collections.Generic; - -namespace Interpreter.Lib.VM -{ - public class Frame - { - private readonly Dictionary _variables = new(); - private readonly Frame _parentFrame; - - public int ReturnAddress { get; } - - public Frame(int returnAddress = 0, Frame parentFrame = null) - { - ReturnAddress = returnAddress; - _parentFrame = parentFrame; - } - - public object this[string id] - { - get => _variables.ContainsKey(id) - ? _variables[id] - : _parentFrame?[id]; - set => _variables[id] = value; - } - } -} \ No newline at end of file diff --git a/Interpreter.Lib/VM/FunctionInfo.cs b/Interpreter.Lib/VM/FunctionInfo.cs deleted file mode 100644 index fd21c491..00000000 --- a/Interpreter.Lib/VM/FunctionInfo.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Interpreter.Lib.VM -{ - public class FunctionInfo - { - public string Id { get; } - - public int Location { get; set; } - - public string MethodOf { get; set; } - - public FunctionInfo(string id, int location = 0, string methodOf = null) - { - Id = id; - Location = location; - MethodOf = methodOf; - } - - public string CallId() => - MethodOf == null - ? Id - : $"{MethodOf}.{Id}"; - - public override string ToString() => $"({Location}, {CallId()})"; - } -} \ No newline at end of file diff --git a/Interpreter.Lib/VM/VirtualMachine.cs b/Interpreter.Lib/VM/VirtualMachine.cs deleted file mode 100644 index 8b8fe1d0..00000000 --- a/Interpreter.Lib/VM/VirtualMachine.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Interpreter.Lib.IR; -using Interpreter.Lib.IR.Instructions; - -namespace Interpreter.Lib.VM -{ - public class VirtualMachine - { - private readonly ControlFlowGraph _cfg; - - public Stack CallStack { get; } = new(); - - public Stack Frames { get; } = new(); - - public Stack<(string Id, object Value)> Arguments { get; } = new(); - - public VirtualMachine(ControlFlowGraph cfg) - { - _cfg = cfg; - } - - public void Run() - { - var block = _cfg.Entry; - var instructions = new Stack(block.Reverse()); - - Frames.Push(new Frame()); - - while (!instructions.Peek().End()) - { - var instruction = instructions.Pop(); - var jump = instruction.Execute(this); - - if (instructions.Any()) - { - continue; - } - - block = _cfg.NextBlock(block, jump); - instructions = new Stack(block.Reverse()); - } - - instructions.Pop().Execute(this); - } - } -} \ No newline at end of file diff --git a/Interpreter.Tests/Interpreter.Tests.csproj b/Interpreter.Tests/Interpreter.Tests.csproj index 52edf26f..19f1a28c 100644 --- a/Interpreter.Tests/Interpreter.Tests.csproj +++ b/Interpreter.Tests/Interpreter.Tests.csproj @@ -1,7 +1,7 @@ - net5.0 + net6.0 false diff --git a/Interpreter.Tests/MockExtensions.cs b/Interpreter.Tests/MockExtensions.cs new file mode 100644 index 00000000..e14a1ecb --- /dev/null +++ b/Interpreter.Tests/MockExtensions.cs @@ -0,0 +1,17 @@ +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.BackEnd.Instructions; +using Moq; + +namespace Interpreter.Tests +{ + public static class MockExtensions + { + public static Mock Trackable(this Mock halt) + { + halt.Setup(x => x.Execute(It.IsAny())) + .Returns(-3).Verifiable(); + halt.Setup(x => x.End()).Returns(true); + return halt; + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Properties/AssemblyInfo.cs b/Interpreter.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..0fe1ef3e --- /dev/null +++ b/Interpreter.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,2 @@ +using Xunit; +[assembly: AssemblyTrait("Category", "Unit")] \ No newline at end of file diff --git a/Interpreter.Tests/Stubs/MapperStub.cs b/Interpreter.Tests/Stubs/MapperStub.cs new file mode 100644 index 00000000..ae5b8e1c --- /dev/null +++ b/Interpreter.Tests/Stubs/MapperStub.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using AutoMapper; +using Interpreter.MappingProfiles; + +namespace Interpreter.Tests.Stubs +{ + public class MapperStub : Mapper + { + public MapperStub() : base(new MapperConfiguration( + x => x.AddProfiles(new List + { + new TokenTypeProfile(), + new StructureProfile() + }) + )) { } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Stubs/SemanticExceptionStub.cs b/Interpreter.Tests/Stubs/SemanticExceptionStub.cs new file mode 100644 index 00000000..84e616a1 --- /dev/null +++ b/Interpreter.Tests/Stubs/SemanticExceptionStub.cs @@ -0,0 +1,6 @@ +using Interpreter.Lib.IR.CheckSemantics.Exceptions; + +namespace Interpreter.Tests.Stubs +{ + public class SemanticExceptionStub : SemanticException { } +} \ No newline at end of file diff --git a/Interpreter.Tests/TestContainer.cs b/Interpreter.Tests/TestContainer.cs deleted file mode 100644 index c8bc508b..00000000 --- a/Interpreter.Tests/TestContainer.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using Interpreter.MappingProfiles; -using Interpreter.Services.Providers; -using Interpreter.Services.Providers.Impl; -using Microsoft.Extensions.DependencyInjection; - -namespace Interpreter.Tests -{ - internal class TestContainer - { - private IServiceCollection ServiceCollection { get; } = new ServiceCollection(); - - private IServiceProvider ServiceProvider { get; set; } - - public TestContainer() - { - ConfigureServices(); - } - - private void ConfigureServices() - { - ServiceCollection.AddTransient(); - ServiceCollection.AddTransient(); - - ServiceCollection.AddAutoMapper(typeof(TokenTypeProfile)); - - ServiceProvider = ServiceCollection.BuildServiceProvider(); - } - - public T Get() => ServiceProvider.GetService(); - } -} \ No newline at end of file diff --git a/Interpreter.Tests/TestData/InstructionsData.cs b/Interpreter.Tests/TestData/InstructionsData.cs new file mode 100644 index 00000000..02e3e607 --- /dev/null +++ b/Interpreter.Tests/TestData/InstructionsData.cs @@ -0,0 +1,107 @@ +using System.Collections; +using System.Collections.Generic; +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; + +namespace Interpreter.Tests.TestData +{ + public class InstructionsData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] + { + new AsString("str", new Name("num"), 0), + "0: str = num as string" + }; + yield return new object[] + { + new BeginFunction(1, new FunctionInfo("func", 1)), + "1: BeginFunction func" + }; + yield return new object[] + { + new CallFunction(new FunctionInfo("func"), 2, 0), + "2: Call (0, func), 0" + }; + yield return new object[] + { + new CallFunction(new FunctionInfo("func"), 2, 0, "ret"), + "2: ret = Call (0, func), 0" + }; + yield return new object[] + { + new CreateArray(3, "arr", 5), + "3: array arr = [5]" + }; + yield return new object[] + { + new CreateObject(4, "obj"), + "4: object obj = {}" + }; + yield return new object[] + { + new DotAssignment("obj", (new Constant("prop", "prop"), new Constant(3, "3")), 5), + "5: obj.prop = 3" + }; + yield return new object[] + { + new Goto(10, 6), + "6: Goto 10" + }; + yield return new object[] + { + new Halt(7), + "7: End" + }; + yield return new object[] + { + new IfNotGoto(new Name("test"), 17, 8), + "8: IfNot test Goto 17" + }; + yield return new object[] + { + new IndexAssignment("arr", (new Constant(1, "1"), new Constant(1, "1")), 9), + "9: arr[1] = 1" + }; + yield return new object[] + { + new Print(10, new Name("str")), + "10: Print str" + }; + yield return new object[] + { + new PushParameter(11, "param", new Name("value")), + "11: PushParameter param = value" + }; + yield return new object[] + { + new RemoveFromArray(12, "arr", new Constant(0, "0")), + "12: RemoveFrom arr at 0" + }; + yield return new object[] + { + new Return(3, 13), + "13: Return" + }; + yield return new object[] + { + new Return(3, 13, new Name("result")), + "13: Return result" + }; + yield return new object[] + { + new Simple("a", (new Name("b"), new Name("c")), "+", 14), + "14: a = b + c" + }; + yield return new object[] + { + new Simple("b", (null, new Name("c")), "-", 14), + "14: b = -c" + }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/Interpreter.Tests/TestData/LexerData.cs b/Interpreter.Tests/TestData/LexerData.cs new file mode 100644 index 00000000..b597294c --- /dev/null +++ b/Interpreter.Tests/TestData/LexerData.cs @@ -0,0 +1,29 @@ +using System.Collections; +using System.Collections.Generic; + +namespace Interpreter.Tests.TestData +{ + public class LexerSuccessData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { "a + b - c return while do" }; + yield return new object[] { "=> abc null true false" }; + yield return new object[] { "{ . } , ( ) [] =?:" }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class LexerFailData : IEnumerable + { + public IEnumerator GetEnumerator() + { + yield return new object[] { "a + v $$$" }; + yield return new object[] { "kkk &" }; + yield return new object[] { "|| |" }; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } +} \ No newline at end of file diff --git a/Interpreter.Tests/TestData/ParserSuccessTestData.cs b/Interpreter.Tests/TestData/ParserData.cs similarity index 100% rename from Interpreter.Tests/TestData/ParserSuccessTestData.cs rename to Interpreter.Tests/TestData/ParserData.cs diff --git a/Interpreter.Tests/Unit/BackEnd/CallTests.cs b/Interpreter.Tests/Unit/BackEnd/CallTests.cs new file mode 100644 index 00000000..c07c6a21 --- /dev/null +++ b/Interpreter.Tests/Unit/BackEnd/CallTests.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using Interpreter.Lib.BackEnd; +using Xunit; + +namespace Interpreter.Tests.Unit.BackEnd +{ + public class CallTests + { + [Fact] + public void ToStringCorrect() + { + var call = new Call(9, new FunctionInfo("func"), + new List<(string Id, object Value)> + { + ("arg", 1) + } + ); + const string expected = "9 => 0: func(arg: 1)"; + Assert.Equal(expected, call.ToString()); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/BackEnd/FunctionInfoTests.cs b/Interpreter.Tests/Unit/BackEnd/FunctionInfoTests.cs new file mode 100644 index 00000000..bc236e7a --- /dev/null +++ b/Interpreter.Tests/Unit/BackEnd/FunctionInfoTests.cs @@ -0,0 +1,14 @@ +using Interpreter.Lib.BackEnd; +using Xunit; + +namespace Interpreter.Tests.Unit.BackEnd +{ + public class FunctionInfoTests + { + [Theory] + [InlineData("func", null, "func")] + [InlineData("func", "obj", "obj.func")] + public void CallIdCorrectTest(string id, string methodOf, string expected) => + Assert.Equal(expected, new FunctionInfo(id, 0, methodOf).CallId()); + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/BackEnd/InstructionsTests.cs b/Interpreter.Tests/Unit/BackEnd/InstructionsTests.cs new file mode 100644 index 00000000..919e4b82 --- /dev/null +++ b/Interpreter.Tests/Unit/BackEnd/InstructionsTests.cs @@ -0,0 +1,40 @@ +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Tests.TestData; +using Moq; +using Xunit; + +namespace Interpreter.Tests.Unit.BackEnd +{ + public class InstructionsTests + { + [Theory] + [ClassData(typeof(InstructionsData))] + public void ToStringCorrectTest(Instruction instruction, string expected) => + Assert.Equal(expected, instruction.ToString()); + + [Fact] + public void ComparisonDependsOnAddressTest() + { + var instruction1 = new Mock(1).Object; + var instruction2 = new Mock(2).Object; + + Assert.Equal(1, instruction2.CompareTo(instruction1)); + } + + [Fact] + public void GotoJumpChangedTest() + { + var @goto = new Goto(0, 1); + @goto.SetJump(5); + Assert.Equal(5, @goto.Jump()); + } + + [Fact] + public void ReturnCallersAddedTest() + { + var @return = new Return(7, 19); + @return.AddCaller(@return.FunctionStart - 2); + Assert.NotEmpty(@return); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/BackEnd/ValuesTests.cs b/Interpreter.Tests/Unit/BackEnd/ValuesTests.cs new file mode 100644 index 00000000..b5535349 --- /dev/null +++ b/Interpreter.Tests/Unit/BackEnd/ValuesTests.cs @@ -0,0 +1,46 @@ +using Interpreter.Lib.BackEnd.Values; +using Xunit; + +namespace Interpreter.Tests.Unit.BackEnd +{ + public class ValuesTests + { + [Fact] + public void ConstantNotEqualToNameTest() + { + var name = new Name("a"); + var constant = new Constant("a", "a"); + + Assert.False(name.Equals(constant)); + Assert.False(constant.Equals(name)); + } + + [Fact] + public void ValueToStringCorrectTest() + { + var name = new Name("bbb"); + var constant = new Constant(1, "1.0"); + + Assert.Equal("bbb", name.ToString()); + Assert.Equal("1.0", constant.ToString()); + } + + [Fact] + public void NameEqualsCorrectTest() + { + var name1 = new Name("name"); + var name2 = new Name("name"); + + Assert.True(name1.Equals(name2)); + } + + [Fact] + public void ConstantEqualsCorrectTest() + { + var constant1 = new Constant(1, "1"); + var constant2 = new Constant(1, "1.0"); + + Assert.True(constant1.Equals(constant2)); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/BackEnd/VirtualMachineTests.cs b/Interpreter.Tests/Unit/BackEnd/VirtualMachineTests.cs new file mode 100644 index 00000000..52794a4a --- /dev/null +++ b/Interpreter.Tests/Unit/BackEnd/VirtualMachineTests.cs @@ -0,0 +1,135 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.IO; +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Moq; +using Xunit; + +namespace Interpreter.Tests.Unit.BackEnd +{ + public class VirtualMachineTests + { + private readonly VirtualMachine _vm; + + public VirtualMachineTests() + { + _vm = new(new(), new(), new(), TextWriter.Null); + } + + [Fact] + public void CorrectPrintToOutTest() + { + var writer = new Mock(); + writer.Setup(x => x.WriteLine(It.IsAny())) + .Verifiable(); + + var vm = new VirtualMachine(new(), new Stack(new[] { new Frame() }), new(), writer.Object); + var print = new Print(0, new Constant(223, "223")); + + print.Execute(vm); + writer.Verify(x => x.WriteLine( + It.Is(v => v!.Equals(223)) + ), Times.Once()); + } + + [Fact] + public void ProgramWithoutHaltWillNotRunTest() + { + var program = new List(); + Assert.Throws(() => _vm.Run(program)); + + program.Add(new Halt(0)); + Assert.Null(Record.Exception(() => _vm.Run(program))); + } + + [Fact] + public void VirtualMachineFramesClearedAfterExecutionTest() + { + var program = new List() + { + new Simple("a", (new Constant(1, "1"), new Constant(2, "2")), "+", 0), + new AsString("b", new Name("a"), 1), + new Halt(2) + }; + + _vm.Run(program); + Assert.Empty(_vm.Frames); + } + + [Fact] + public void VirtualMachineHandlesRecursionTest() + { + var halt = new Mock(12).Trackable(); + var factorial = new FunctionInfo("fact", 1); + var program = new List + { + new Goto(10, 0), + new BeginFunction(1, factorial), + new Simple("_t2", (new Name("n"), new Constant(2, "2")), "<", 2), + new IfNotGoto(new Name("_t2"), 5, 3), + new Return(1, 4, new Name("n")), + new Simple("_t5", (new Name("n"), new Constant(1, "1")), "-", 5), + new PushParameter(6, "n", new Name("_t5")), + new CallFunction(factorial, 7, 1, "f"), + new Simple("_t8", (new Name("n"), new Name("f")), "*", 8), + new Return(1, 9, new Name("_t8")), + new PushParameter(10, "n", new Constant(6, "6")), + new CallFunction(factorial, 11, 1, "fa6"), + halt.Object + }; + + _vm.Run(program); + Assert.Empty(_vm.CallStack); + Assert.Empty(_vm.Arguments); + halt.Verify(x => x.Execute( + It.Is( + vm => Convert.ToInt32(vm.Frames.Peek()["fa6"]) == 720 + ) + ), Times.Once()); + _vm.Frames.Pop(); + } + + [Fact] + public void CreateArrayReservesCertainSpaceTest() + { + var vm = new VirtualMachine(); + vm.Frames.Push(new Frame()); + + var createArray = new CreateArray(0, "arr", 6); + createArray.Execute(vm); + Assert.Equal(6, ((List) vm.Frames.Peek()["arr"]).Count); + + var indexAssignment = new IndexAssignment("arr", (new Constant(0, "0"), new Constant(0, "0")), 1); + indexAssignment.Execute(vm); + Assert.Equal(0, ((List) vm.Frames.Peek()["arr"])[0]); + + var removeFromArray = new RemoveFromArray(2, "arr", new Constant(5, "5")); + removeFromArray.Execute(vm); + Assert.Equal(5, ((List) vm.Frames.Peek()["arr"]).Count); + } + + [Fact] + public void ObjectCreationTest() + { + var halt = new Mock(2).Trackable(); + var program = new List + { + new CreateObject(0, "obj"), + new DotAssignment("obj", (new Constant("prop", "prop"), new Constant(null, "null")), 1), + halt.Object + }; + + _vm.Run(program); + halt.Verify(x => x.Execute( + It.Is( + // ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract + vm => ((Dictionary)vm.Frames.Peek()["obj"])["prop"] == null + ) + ), Times.Once()); + _vm.Frames.Pop(); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/FrontEnd/LexerTests.cs b/Interpreter.Tests/Unit/FrontEnd/LexerTests.cs new file mode 100644 index 00000000..f65651b6 --- /dev/null +++ b/Interpreter.Tests/Unit/FrontEnd/LexerTests.cs @@ -0,0 +1,45 @@ +using System.Linq; +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.FrontEnd.GetTokens.Impl; +using Interpreter.Models; +using Interpreter.Tests.Stubs; +using Interpreter.Tests.TestData; +using Xunit; + +namespace Interpreter.Tests.Unit.FrontEnd +{ + public class LexerTests + { + private readonly Lexer _lexer; + + public LexerTests() + { + var mapper = new MapperStub(); + _lexer = new Lexer(mapper.Map(new())); + } + + [Theory] + [ClassData(typeof(LexerSuccessData))] + public void LexerDoesNotThrowTest(string text) => + Assert.Null(Record.Exception(() => _lexer.GetTokens(text))); + + [Theory] + [ClassData(typeof(LexerFailData))] + public void LexerThrowsErrorTest(string text) => + Assert.Throws(() => _lexer.GetTokens(text)); + + [Fact] + public void LexerToStringCorrectTest() + { + const string text = "8"; + var tokens = _lexer.GetTokens(text); + Assert.Contains("EOP", _lexer.ToString()); + Assert.Equal("IntegerLiteral (1, 1)-(1, 2): 8", tokens.First().ToString()); + } + + [Fact] + public void EmptyTextTest() => + Assert.NotEmpty(_lexer.GetTokens("")); + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs b/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs new file mode 100644 index 00000000..13601e51 --- /dev/null +++ b/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs @@ -0,0 +1,37 @@ +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.FrontEnd.GetTokens.Impl; +using Interpreter.Lib.FrontEnd.TopDownParse; +using Interpreter.Lib.FrontEnd.TopDownParse.Impl; +using Interpreter.Models; +using Interpreter.Tests.Stubs; +using Interpreter.Tests.TestData; +using Xunit; + +namespace Interpreter.Tests.Unit.FrontEnd +{ + public class ParserTests + { + private readonly IParser _parser; + + public ParserTests() + { + var mapper = new MapperStub(); + + _parser = new Parser(new Lexer( + mapper.Map(new()) + )); + } + + [Theory] + [ClassData(typeof(ParserSuccessTestData))] + public void ParserDoesNotThrowTest(string text) + { + var ex = Record.Exception(() => + { + // ReSharper disable once UnusedVariable + var ast = _parser.TopDownParse(text); + }); + Assert.Null(ex); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/FrontEnd/StructureTests.cs b/Interpreter.Tests/Unit/FrontEnd/StructureTests.cs new file mode 100644 index 00000000..645a8438 --- /dev/null +++ b/Interpreter.Tests/Unit/FrontEnd/StructureTests.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; +using Xunit; + +namespace Interpreter.Tests.Unit.FrontEnd +{ + public class StructureTests + { + [Fact] + public void ToStringCorrectTest() + { + var tokenTypes = new List + { + new ("MyToken", "[m|M][y|Y]", 2), + new ("OneToSeven", "[1-7]", 1) + }; + var structure = new Structure(tokenTypes); + + var expectedText = string.Join('\n', + new List + { + "OneToSeven [1-7]", + "MyToken [m|M][y|Y]", + "EOP ", + "ERROR \\S+" + } + ); + Assert.Equal(expectedText,structure.ToString()); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/AstNodeTests.cs b/Interpreter.Tests/Unit/IR/AstNodeTests.cs similarity index 55% rename from Interpreter.Tests/Unit/AstNodeTests.cs rename to Interpreter.Tests/Unit/IR/AstNodeTests.cs index d7c18874..be05ddcc 100644 --- a/Interpreter.Tests/Unit/AstNodeTests.cs +++ b/Interpreter.Tests/Unit/IR/AstNodeTests.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; -using Interpreter.Lib.Semantic.Nodes; -using Interpreter.Lib.Semantic.Nodes.Declarations; -using Interpreter.Lib.Semantic.Nodes.Statements; -using Interpreter.Lib.Semantic.Symbols; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.IR.Ast.Nodes; +using Interpreter.Lib.IR.Ast.Nodes.Declarations; +using Interpreter.Lib.IR.Ast.Nodes.Statements; +using Interpreter.Lib.IR.CheckSemantics.Types; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; using Moq; using Xunit; -namespace Interpreter.Tests.Unit +namespace Interpreter.Tests.Unit.IR { public class AstNodeTests { @@ -15,7 +15,7 @@ public class AstNodeTests public void PrecedenceTest() { var fType = new Mock(new Mock("").Object, new List()); - var funcSymbol = new Mock("f", new List(), fType.Object); + var funcSymbol = new FunctionSymbol("f", new List(), fType.Object); var lexicalDecl = new LexicalDeclaration(false); var stmtItemList = new List @@ -23,7 +23,7 @@ public void PrecedenceTest() lexicalDecl }; // ReSharper disable once UnusedVariable - var func = new FunctionDeclaration(funcSymbol.Object, new BlockStatement(stmtItemList)); + var func = new FunctionDeclaration(funcSymbol, new BlockStatement(stmtItemList)); Assert.True(lexicalDecl.ChildOf()); } diff --git a/Interpreter.Tests/Unit/ExpressionTests.cs b/Interpreter.Tests/Unit/IR/ExpressionTests.cs similarity index 69% rename from Interpreter.Tests/Unit/ExpressionTests.cs rename to Interpreter.Tests/Unit/IR/ExpressionTests.cs index d921d847..2fa0ad48 100644 --- a/Interpreter.Tests/Unit/ExpressionTests.cs +++ b/Interpreter.Tests/Unit/IR/ExpressionTests.cs @@ -1,9 +1,9 @@ -using Interpreter.Lib.Semantic.Nodes.Expressions; -using Interpreter.Lib.Semantic.Nodes.Expressions.PrimaryExpressions; -using Interpreter.Lib.Semantic.Types; +using Interpreter.Lib.IR.Ast.Nodes.Expressions; +using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; +using Interpreter.Lib.IR.CheckSemantics.Types; using Xunit; -namespace Interpreter.Tests.Unit +namespace Interpreter.Tests.Unit.IR { public class ExpressionTests { diff --git a/Interpreter.Tests/Unit/SymbolTableTests.cs b/Interpreter.Tests/Unit/IR/SymbolTableTests.cs similarity index 72% rename from Interpreter.Tests/Unit/SymbolTableTests.cs rename to Interpreter.Tests/Unit/IR/SymbolTableTests.cs index 5e5fa004..0a07cb35 100644 --- a/Interpreter.Tests/Unit/SymbolTableTests.cs +++ b/Interpreter.Tests/Unit/IR/SymbolTableTests.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; using System.Linq; -using Interpreter.Lib.Semantic; -using Interpreter.Lib.Semantic.Nodes; -using Interpreter.Lib.Semantic.Symbols; +using Interpreter.Lib.IR.Ast.Nodes; +using Interpreter.Lib.IR.CheckSemantics.Variables; +using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; using Moq; using Xunit; +using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Tests.Unit +namespace Interpreter.Tests.Unit.IR { public class SymbolTableTests { @@ -15,9 +16,11 @@ public class SymbolTableTests public void FindSymbolTest() { const string id = "ident"; + var type = new Mock(id); - var symbol = new Mock(id); + var symbol = new Mock(id, type.Object); symbol.Setup(s => s.Id).Returns(id); + symbol.Setup(s => s.Type).Returns(type.Object); var outerScope = new SymbolTable(); var innerScope = new SymbolTable(); @@ -45,9 +48,11 @@ public void FlatteningScopeTest() script.ToList().ForEach(node => node.SymbolTable = table); const string id = "ident"; + var type = new Mock(id); - var symbol = new Mock(id); + var symbol = new Mock(id, type.Object); symbol.Setup(s => s.Id).Returns(id); + symbol.Setup(s => s.Type).Returns(type.Object); script.SymbolTable.AddSymbol(symbol.Object); diff --git a/Interpreter.Tests/Unit/TypeTests.cs b/Interpreter.Tests/Unit/IR/TypeTests.cs similarity index 97% rename from Interpreter.Tests/Unit/TypeTests.cs rename to Interpreter.Tests/Unit/IR/TypeTests.cs index 931a23a6..592c6aa1 100644 --- a/Interpreter.Tests/Unit/TypeTests.cs +++ b/Interpreter.Tests/Unit/IR/TypeTests.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; -using Interpreter.Lib.Semantic.Types; -using Interpreter.Lib.Semantic.Utils; +using Interpreter.Lib.IR.CheckSemantics.Types; using Xunit; -namespace Interpreter.Tests.Unit +namespace Interpreter.Tests.Unit.IR { public class TypeTests { diff --git a/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs b/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs new file mode 100644 index 00000000..ea28a038 --- /dev/null +++ b/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.TopDownParse; +using Interpreter.Lib.IR.Ast; +using Interpreter.Services.Executor.Impl; +using Interpreter.Services.Parsing; +using Interpreter.Tests.Stubs; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Interpreter.Tests.Unit.Infrastructure +{ + public class ExecutorTests + { + private readonly Mock _settings; + private readonly Mock _parsingService; + + public ExecutorTests() + { + _settings = new Mock(); + _settings.Setup(x => x.Dump).Returns(false); + _settings.Setup(x => x.InputFilePath).Returns("file.js"); + + _parsingService = new Mock(); + } + + [Fact] + public void ExecuteGoesOkTest() + { + var ast = new Mock(); + ast.Setup(x => x.GetInstructions()) + .Returns(new List { new Halt(0) }); + + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Returns(ast.Object); + + var executor = new Executor(_parsingService.Object, Options.Create(_settings.Object)); + Assert.Null(Record.Exception(() => executor.Execute())); + } + + [Fact] + public void SemanticExceptionCaughtTest() + { + var ast = new Mock(); + ast.Setup(x => x.GetInstructions()) + .Throws(); + + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Returns(ast.Object); + + var executor = new Executor(_parsingService.Object, Options.Create(_settings.Object)); + Assert.Null(Record.Exception(() => executor.Execute())); + } + + [Fact] + public void LexerExceptionCaughtTest() + { + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Throws(); + + var executor = new Executor(_parsingService.Object, Options.Create(_settings.Object)); + Assert.Null(Record.Exception(() => executor.Execute())); + } + + [Fact] + public void ParserExceptionCaughtTest() + { + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Throws(); + + var executor = new Executor(_parsingService.Object, Options.Create(_settings.Object)); + Assert.Null(Record.Exception(() => executor.Execute())); + } + + [Fact] + public void InternalInterpreterErrorCaughtTest() + { + var instruction = new Mock(MockBehavior.Default, 0); + instruction.Setup(x => x.Execute(It.IsAny())) + .Throws(); + + var ast = new Mock(); + ast.Setup(x => x.GetInstructions()) + .Returns(new List { instruction.Object, new Halt(1) }); + + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Returns(ast.Object); + + var executor = new Executor(_parsingService.Object, Options.Create(_settings.Object)); + Assert.Null(Record.Exception(() => executor.Execute())); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs b/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs new file mode 100644 index 00000000..37ff1181 --- /dev/null +++ b/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs @@ -0,0 +1,34 @@ +using Interpreter.Lib.FrontEnd.TopDownParse; +using Interpreter.Lib.IR.Ast; +using Interpreter.Services.Parsing.Impl; +using Interpreter.Services.Providers; +using Moq; +using Xunit; + +namespace Interpreter.Tests.Unit.Infrastructure +{ + public class ParsingServiceTests + { + [Fact] + public void CertainTextHasBeenParsedTest() + { + const string text = "let x = 1 + 2 - 3"; + + var ast = new Mock(); + var parser = new Mock(); + parser.Setup(x => x.TopDownParse(It.IsAny())) + .Returns(ast.Object).Verifiable(); + + var parserProvider = new Mock(); + parserProvider.Setup(x => x.CreateParser()) + .Returns(parser.Object); + + var parsingService = new ParsingService(parserProvider.Object); + parsingService.Parse(text); + + parser.Verify(x => x.TopDownParse( + It.Is(s => s == text) + ), Times.Once()); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/Infrastructure/ProvidersTests.cs b/Interpreter.Tests/Unit/Infrastructure/ProvidersTests.cs new file mode 100644 index 00000000..37664664 --- /dev/null +++ b/Interpreter.Tests/Unit/Infrastructure/ProvidersTests.cs @@ -0,0 +1,60 @@ +using System; +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.GetTokens.Impl; +using Interpreter.Lib.FrontEnd.TopDownParse.Impl; +using Interpreter.Services.Providers; +using Interpreter.Services.Providers.Impl.LexerProvider; +using Interpreter.Services.Providers.Impl.ParserProvider; +using Interpreter.Tests.Stubs; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Interpreter.Tests.Unit.Infrastructure +{ + public class ProvidersTests + { + [Theory] + [InlineData(typeof(Lexer), false)] + [InlineData(typeof(LoggingLexer), true)] + public void CertainLexerProvidedTest(Type lexerType, bool dump) + { + var options = new Mock>(); + options.Setup(x => x.Value) + .Returns(new CommandLineSettings + { + Dump = dump, + InputFilePath = "file.js" + }); + + var lexerProvider = new LexerProvider(new MapperStub(), options.Object); + var lexer = lexerProvider.CreateLexer(); + + Assert.IsType(lexerType, lexer); + } + + [Theory] + [InlineData(typeof(Parser), false)] + [InlineData(typeof(LoggingParser), true)] + public void CertainParserProvidedTest(Type parserType, bool dump) + { + var options = new Mock>(); + options.Setup(x => x.Value) + .Returns(new CommandLineSettings + { + Dump = dump, + InputFilePath = "file.js" + }); + + var lexer = new Mock(); + var lexerProvider = new Mock(); + lexerProvider.Setup(x => x.CreateLexer()) + .Returns(lexer.Object); + + var parserProvider = new ParserProvider(lexerProvider.Object, options.Object); + var parser = parserProvider.CreateParser(); + + Assert.IsType(parserType, parser); + } + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/OptimizerTests.cs b/Interpreter.Tests/Unit/OptimizerTests.cs deleted file mode 100644 index c360d1cf..00000000 --- a/Interpreter.Tests/Unit/OptimizerTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.IR.Optimizers; -using Interpreter.Lib.VM.Values; -using Xunit; - -namespace Interpreter.Tests.Unit -{ - public class OptimizerTests - { - private IOptimizer _optimizer; - - [Fact] - public void IdentityExpressionTests() - { - _optimizer = new IdentityExpression( - new Simple( - "i", (new Constant(0, "0"), new Name("x")), "+", 0 - ) - ); - - Assert.True(_optimizer.Test()); - _optimizer.Optimize(); - Assert.Equal("0: i = x", _optimizer.Instruction.ToString()); - - - _optimizer = new IdentityExpression( - new Simple( - "i", (new Constant(1, "1"), new Name("x")), "*", 0 - ) - ); - Assert.True(_optimizer.Test()); - _optimizer.Optimize(); - Assert.Equal("0: i = x", _optimizer.Instruction.ToString()); - - _optimizer = new IdentityExpression( - new Simple( - "i", (new Constant(2, "2"), new Name("x")), "+", 0 - ) - ); - Assert.False(_optimizer.Test()); - } - } -} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/ParserTests.cs b/Interpreter.Tests/Unit/ParserTests.cs deleted file mode 100644 index 00908e5b..00000000 --- a/Interpreter.Tests/Unit/ParserTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Syntactic; -using Interpreter.Models; -using Interpreter.Services.Providers; -using Interpreter.Tests.TestData; -using Xunit; - -namespace Interpreter.Tests.Unit -{ - public class ParserTests - { - private readonly TestContainer _container; - private readonly LexerQueryModel _query; - - public ParserTests() - { - _container = new TestContainer(); - _query = new LexerQueryModel(); - } - - private Parser GetParser(string text) - { - _query.Text = text; - var lexerCreator = _container.Get(); - var parserCreator = _container.Get(); - - var lexer = lexerCreator.CreateLexer(_query); - var parser = parserCreator.CreateParser(lexer); - return parser; - } - - [Theory] - [ClassData(typeof(ParserSuccessTestData))] - public void ParserDoesNotThrowTest(string text) - { - var parser = GetParser(text); - - var ex = Record.Exception(() => - { - // ReSharper disable once UnusedVariable - var ast = parser.TopDownParse(); - }); - Assert.Null(ex); - } - } -} \ No newline at end of file diff --git a/Interpreter/CommandLineSettings.cs b/Interpreter/CommandLineSettings.cs index 8a1e0879..d94f1c2c 100644 --- a/Interpreter/CommandLineSettings.cs +++ b/Interpreter/CommandLineSettings.cs @@ -8,15 +8,16 @@ namespace Interpreter { [SuppressMessage("ReSharper", "UnusedMember.Global")] - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] [SuppressMessage("ReSharper", "PropertyCanBeMadeInitOnly.Global")] + [ExcludeFromCodeCoverage] + // ReSharper disable once ClassWithVirtualMembersNeverInherited.Global public class CommandLineSettings { [Value(0, MetaName = "InputFilePath", Required = true, HelpText = "Path to input file")] - public string InputFilePath { get; set; } + public virtual string InputFilePath { get; set; } [Option('d', "dump", Default = false, HelpText = "Show dump data of interpreter")] - public bool Dump { get; set; } + public virtual bool Dump { get; set; } [Usage(ApplicationAlias = "Interpreter")] public static IEnumerable Examples @@ -32,10 +33,9 @@ public static IEnumerable Examples public string GetInputFileName() => InputFilePath.Split(".js")[0]; - public LexerQueryModel CreateLexerQuery() => - new() - { - Text = File.ReadAllText(InputFilePath) - }; + public StructureModel StructureModel { get; } = new(); + + public virtual string GetText() => + File.ReadAllText(InputFilePath); } } \ No newline at end of file diff --git a/Interpreter/Interpreter.csproj b/Interpreter/Interpreter.csproj index baea5a3a..a12630c8 100644 --- a/Interpreter/Interpreter.csproj +++ b/Interpreter/Interpreter.csproj @@ -2,8 +2,8 @@ Exe - net5.0 - 1.0.2 + net6.0 + 1.1.2 diff --git a/Interpreter/MappingProfiles/StructureProfile.cs b/Interpreter/MappingProfiles/StructureProfile.cs new file mode 100644 index 00000000..817f534c --- /dev/null +++ b/Interpreter/MappingProfiles/StructureProfile.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using AutoMapper; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; +using Interpreter.Models; + +namespace Interpreter.MappingProfiles +{ + public class StructureProfile : Profile + { + public StructureProfile() + { + CreateMap() + .ConstructUsing((src, context) => + new Structure(context.Mapper + .Map, List> + (src.TokenTypes))); + } + } +} \ No newline at end of file diff --git a/Interpreter/MappingProfiles/TokenTypeProfile.cs b/Interpreter/MappingProfiles/TokenTypeProfile.cs index ee75f8ba..bc7022a9 100644 --- a/Interpreter/MappingProfiles/TokenTypeProfile.cs +++ b/Interpreter/MappingProfiles/TokenTypeProfile.cs @@ -1,5 +1,5 @@ using AutoMapper; -using Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes; +using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; using Interpreter.Models; namespace Interpreter.MappingProfiles diff --git a/Interpreter/Models/LexerQueryModel.cs b/Interpreter/Models/LexerQueryModel.cs deleted file mode 100644 index 8976cc47..00000000 --- a/Interpreter/Models/LexerQueryModel.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using AutoMapper; -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.RBNF.Analysis.Lexical.TokenTypes; -using Newtonsoft.Json; - -namespace Interpreter.Models -{ - public class LexerQueryModel - { - [JsonProperty] private List TokenTypes { get; set; } - - public LexerQueryModel() - { - TokenTypes = JsonConvert.DeserializeObject>( - Interpreter.TokenTypes.Json - ); - } - - public string Text { get; set; } - - public Structure GetDomain(IMapper mapper) => - new(mapper.Map>(TokenTypes)); - } -} \ No newline at end of file diff --git a/Interpreter/Models/StructureModel.cs b/Interpreter/Models/StructureModel.cs new file mode 100644 index 00000000..b0dbe984 --- /dev/null +++ b/Interpreter/Models/StructureModel.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using Newtonsoft.Json; + +namespace Interpreter.Models +{ + [ExcludeFromCodeCoverage] + public class StructureModel + { + public List TokenTypes { get; } + + public StructureModel() + { + TokenTypes = JsonConvert.DeserializeObject>( + Interpreter.TokenTypes.Json + ); + } + } +} \ No newline at end of file diff --git a/Interpreter/Models/TokenTypeModel.cs b/Interpreter/Models/TokenTypeModel.cs index cdddb493..580e119b 100644 --- a/Interpreter/Models/TokenTypeModel.cs +++ b/Interpreter/Models/TokenTypeModel.cs @@ -5,6 +5,7 @@ namespace Interpreter.Models // ReSharper disable once ClassNeverInstantiated.Global [SuppressMessage("ReSharper", "UnusedMember.Global")] [SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Global")] + [ExcludeFromCodeCoverage] public record TokenTypeModel { public string Tag { get; init; } diff --git a/Interpreter/Program.cs b/Interpreter/Program.cs index ee749040..5e2baac3 100644 --- a/Interpreter/Program.cs +++ b/Interpreter/Program.cs @@ -5,25 +5,28 @@ using Interpreter.MappingProfiles; using Interpreter.Services.Executor; using Interpreter.Services.Executor.Impl; +using Interpreter.Services.Parsing; +using Interpreter.Services.Parsing.Impl; using Interpreter.Services.Providers; -using Interpreter.Services.Providers.Impl; +using Interpreter.Services.Providers.Impl.LexerProvider; +using Interpreter.Services.Providers.Impl.ParserProvider; using Microsoft.Extensions.Options; namespace Interpreter { + [ExcludeFromCodeCoverage] public static class Program { private static IServiceCollection ServiceCollection { get; } = new ServiceCollection(); private static IServiceProvider ServiceProvider { get; set; } - [SuppressMessage("ReSharper", "PossibleNullReferenceException")] private static void Main(string[] args) => Parser.Default.ParseArguments(args) .WithParsed(options => { ConfigureServices(options); ServiceProvider - .GetService() + .GetService()! .Execute(); }) .WithNotParsed(errors => errors.Output()); @@ -31,10 +34,11 @@ private static void Main(string[] args) => private static void ConfigureServices(CommandLineSettings settings) { - ServiceCollection.AddTransient(); - ServiceCollection.AddTransient(); + ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); - ServiceCollection.AddAutoMapper(typeof(TokenTypeProfile)); + ServiceCollection.AddAutoMapper(typeof(TokenTypeProfile), typeof(StructureProfile)); ServiceCollection.AddSingleton(); diff --git a/Interpreter/Services/Executor/Impl/Executor.cs b/Interpreter/Services/Executor/Impl/Executor.cs index 9ef946aa..53ac4d90 100644 --- a/Interpreter/Services/Executor/Impl/Executor.cs +++ b/Interpreter/Services/Executor/Impl/Executor.cs @@ -1,79 +1,33 @@ using System; -using System.IO; -using System.Linq; -using Interpreter.Lib.IR; -using Interpreter.Lib.IR.Instructions; -using Interpreter.Lib.IR.Optimizers; -using Interpreter.Lib.RBNF.Analysis.Exceptions; -using Interpreter.Lib.Semantic.Analysis; -using Interpreter.Lib.Semantic.Exceptions; -using Interpreter.Lib.VM; -using Interpreter.Services.Providers; +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.TopDownParse; +using Interpreter.Lib.IR.CheckSemantics.Exceptions; +using Interpreter.Services.Parsing; using Microsoft.Extensions.Options; namespace Interpreter.Services.Executor.Impl { public class Executor : IExecutor { - private readonly ILexerProvider _lexerProvider; - private readonly IParserProvider _parserProvider; + private readonly IParsingService _parsingService; private readonly CommandLineSettings _commandLineSettings; - public Executor(ILexerProvider lexerProvider, IParserProvider parserProvider, IOptions optionsProvider) + public Executor(IParsingService parsingService, IOptions options) { - _lexerProvider = lexerProvider; - _parserProvider = parserProvider; - _commandLineSettings = optionsProvider.Value; + _parsingService = parsingService; + _commandLineSettings = options.Value; } public void Execute() { try { - var lexer = _lexerProvider - .CreateLexer(_commandLineSettings.CreateLexerQuery()); - - var parser = _parserProvider - .CreateParser(lexer); - - using var ast = parser.TopDownParse(); - - ast.Check(new SemanticAnalyzer(node => node.SemanticCheck())); - + var ast = _parsingService.Parse(_commandLineSettings.GetText()); var instructions = ast.GetInstructions(); - var cfg = new ControlFlowGraph( - new BasicBlockBuilder(instructions) - .GetBasicBlocks() - ); - - cfg.OptimizeInstructions( - i => new IdentityExpression(i as Simple), - i => new ZeroExpression(i as Simple) - ); - - var vm = new VirtualMachine(cfg); - vm.Run(); - - if (_commandLineSettings.Dump) - { - var fileName = _commandLineSettings.GetInputFileName(); - File.WriteAllLines( - $"{fileName}.tac", - instructions.OrderBy(i => i).Select(i => i.ToString()) - ); - - File.WriteAllText( - $"{fileName}.tokens", - string.Join('\n', lexer) - ); - - var astDot = ast.ToString(); - File.WriteAllText("ast.dot", astDot); - - var cfgDot = cfg.ToString(); - File.WriteAllText("cfg.dot", cfgDot); - } + var vm = new VirtualMachine(); + vm.Run(instructions); } catch (Exception ex) when (ex is LexerException or ParserException or SemanticException) diff --git a/Interpreter/Services/Parsing/IParsingService.cs b/Interpreter/Services/Parsing/IParsingService.cs new file mode 100644 index 00000000..312e5b70 --- /dev/null +++ b/Interpreter/Services/Parsing/IParsingService.cs @@ -0,0 +1,9 @@ +using Interpreter.Lib.IR.Ast; + +namespace Interpreter.Services.Parsing +{ + public interface IParsingService + { + IAbstractSyntaxTree Parse(string text); + } +} \ No newline at end of file diff --git a/Interpreter/Services/Parsing/Impl/ParsingService.cs b/Interpreter/Services/Parsing/Impl/ParsingService.cs new file mode 100644 index 00000000..0f105154 --- /dev/null +++ b/Interpreter/Services/Parsing/Impl/ParsingService.cs @@ -0,0 +1,21 @@ +using Interpreter.Lib.IR.Ast; +using Interpreter.Services.Providers; + +namespace Interpreter.Services.Parsing.Impl +{ + public class ParsingService : IParsingService + { + private readonly IParserProvider _parserProvider; + + public ParsingService(IParserProvider parserProvider) + { + _parserProvider = parserProvider; + } + + public IAbstractSyntaxTree Parse(string text) + { + var parser = _parserProvider.CreateParser(); + return parser.TopDownParse(text); + } + } +} \ No newline at end of file diff --git a/Interpreter/Services/Providers/ILexerProvider.cs b/Interpreter/Services/Providers/ILexerProvider.cs index 187e9821..4011e48a 100644 --- a/Interpreter/Services/Providers/ILexerProvider.cs +++ b/Interpreter/Services/Providers/ILexerProvider.cs @@ -1,10 +1,9 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Models; +using Interpreter.Lib.FrontEnd.GetTokens; namespace Interpreter.Services.Providers { public interface ILexerProvider { - Lexer CreateLexer(LexerQueryModel lexerQuery); + ILexer CreateLexer(); } } \ No newline at end of file diff --git a/Interpreter/Services/Providers/IParserProvider.cs b/Interpreter/Services/Providers/IParserProvider.cs index f0726014..48b188c5 100644 --- a/Interpreter/Services/Providers/IParserProvider.cs +++ b/Interpreter/Services/Providers/IParserProvider.cs @@ -1,10 +1,9 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.RBNF.Analysis.Syntactic; +using Interpreter.Lib.FrontEnd.TopDownParse; namespace Interpreter.Services.Providers { public interface IParserProvider { - Parser CreateParser(Lexer lexer); + IParser CreateParser(); } } \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/LexerProvider.cs b/Interpreter/Services/Providers/Impl/LexerProvider.cs deleted file mode 100644 index 7b0b456b..00000000 --- a/Interpreter/Services/Providers/Impl/LexerProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -using AutoMapper; -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Models; - -namespace Interpreter.Services.Providers.Impl -{ - public class LexerProvider : ILexerProvider - { - private readonly IMapper _mapper; - - public LexerProvider(IMapper mapper) - { - _mapper = mapper; - } - - public Lexer CreateLexer(LexerQueryModel lexerQuery) - { - var domain = lexerQuery.GetDomain(_mapper); - var source = lexerQuery.Text; - return new Lexer(domain, source); - } - } -} \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs b/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs new file mode 100644 index 00000000..ddfc7ddf --- /dev/null +++ b/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs @@ -0,0 +1,30 @@ +using AutoMapper; +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.GetTokens.Data; +using Interpreter.Lib.FrontEnd.GetTokens.Impl; +using Interpreter.Models; +using Microsoft.Extensions.Options; + +namespace Interpreter.Services.Providers.Impl.LexerProvider +{ + public class LexerProvider : ILexerProvider + { + private readonly IMapper _mapper; + private readonly CommandLineSettings _settings; + + public LexerProvider(IMapper mapper, IOptions options) + { + _mapper = mapper; + _settings = options.Value; + } + + public ILexer CreateLexer() + { + var domain = _mapper.Map(_settings.StructureModel); + var lexer = new Lexer(domain); + return _settings.Dump + ? new LoggingLexer(lexer, _settings.GetInputFileName()) + : lexer; + } + } +} \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/LexerProvider/LoggingLexer.cs b/Interpreter/Services/Providers/Impl/LexerProvider/LoggingLexer.cs new file mode 100644 index 00000000..472ef503 --- /dev/null +++ b/Interpreter/Services/Providers/Impl/LexerProvider/LoggingLexer.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using System.IO; +using Interpreter.Lib.FrontEnd.GetTokens; +using Interpreter.Lib.FrontEnd.GetTokens.Data; + +namespace Interpreter.Services.Providers.Impl.LexerProvider +{ + public class LoggingLexer : ILexer + { + private readonly ILexer _lexer; + private readonly string _fileName; + + public LoggingLexer(ILexer lexer, string fileName) + { + _lexer = lexer; + _fileName = fileName; + } + + public Structure Structure => _lexer.Structure; + + public List GetTokens(string text) + { + var tokens = _lexer.GetTokens(text); + File.WriteAllText( + $"{_fileName}.tokens", + _lexer.ToString() + ); + return tokens; + } + } +} \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/ParserProvider.cs b/Interpreter/Services/Providers/Impl/ParserProvider.cs deleted file mode 100644 index 4a70036d..00000000 --- a/Interpreter/Services/Providers/Impl/ParserProvider.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Interpreter.Lib.RBNF.Analysis.Lexical; -using Interpreter.Lib.RBNF.Analysis.Syntactic; - -namespace Interpreter.Services.Providers.Impl -{ - public class ParserProvider : IParserProvider - { - public Parser CreateParser(Lexer lexer) => new (lexer); - } -} \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs new file mode 100644 index 00000000..b6aa20d6 --- /dev/null +++ b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.IR.Ast; + +namespace Interpreter.Services.Providers.Impl.ParserProvider +{ + public class LoggingAbstractSyntaxTree : IAbstractSyntaxTree + { + private readonly IAbstractSyntaxTree _ast; + private readonly string _fileName; + + public LoggingAbstractSyntaxTree(IAbstractSyntaxTree ast, string fileName) + { + _ast = ast; + _fileName = fileName; + } + + public List GetInstructions() + { + var instructions = _ast.GetInstructions(); + File.WriteAllLines( + $"{_fileName}.tac", + instructions.OrderBy(i => i).Select(i => i.ToString()) + ); + return instructions; + } + } +} \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/ParserProvider/LoggingParser.cs b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingParser.cs new file mode 100644 index 00000000..05615703 --- /dev/null +++ b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingParser.cs @@ -0,0 +1,26 @@ +using System.IO; +using Interpreter.Lib.FrontEnd.TopDownParse; +using Interpreter.Lib.IR.Ast; + +namespace Interpreter.Services.Providers.Impl.ParserProvider +{ + public class LoggingParser : IParser + { + private readonly IParser _parser; + private readonly string _fileName; + + public LoggingParser(IParser parser, string fileName) + { + _parser = parser; + _fileName = fileName; + } + + public IAbstractSyntaxTree TopDownParse(string text) + { + var ast = _parser.TopDownParse(text); + var astDot = ast.ToString(); + File.WriteAllText("ast.dot", astDot); + return new LoggingAbstractSyntaxTree(ast, _fileName); + } + } +} \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs b/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs new file mode 100644 index 00000000..658faab4 --- /dev/null +++ b/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs @@ -0,0 +1,27 @@ +using Interpreter.Lib.FrontEnd.TopDownParse; +using Parser = Interpreter.Lib.FrontEnd.TopDownParse.Impl.Parser; +using Microsoft.Extensions.Options; + +namespace Interpreter.Services.Providers.Impl.ParserProvider +{ + public class ParserProvider : IParserProvider + { + private readonly ILexerProvider _lexerProvider; + private readonly CommandLineSettings _settings; + + public ParserProvider(ILexerProvider lexerProvider, IOptions options) + { + _lexerProvider = lexerProvider; + _settings = options.Value; + } + + public IParser CreateParser() + { + var lexer = _lexerProvider.CreateLexer(); + var parser = new Parser(lexer); + return _settings.Dump + ? new LoggingParser(parser, _settings.GetInputFileName()) + : parser; + } + } +} \ No newline at end of file diff --git a/Interpreter/TokenTypes.cs b/Interpreter/TokenTypes.cs index 707e37cf..ec2636f0 100644 --- a/Interpreter/TokenTypes.cs +++ b/Interpreter/TokenTypes.cs @@ -2,7 +2,7 @@ namespace Interpreter { public static class TokenTypes { - public static readonly string Json = @"[ + public const string Json = @"[ { ""tag"": ""Comment"", ""pattern"": ""[\/]{2}.*"", diff --git a/Readme.md b/Readme.md index d0716191..d8a22514 100644 --- a/Readme.md +++ b/Readme.md @@ -14,7 +14,7 @@ _Minimum allowed line rate is `20%`_ За основу был взят стандарт [ECMA-262](https://www.ecma-international.org/publications-and-standards/standards/ecma-262/) -[Лексическая структура](Interpreter/tokenTypes.json) +[Лексическая структура](Interpreter/TokenTypes.cs) [Грамматика](Interpreter/grammar.txt) @@ -158,7 +158,7 @@ let s = v2d as string ### Требования -- .NET 5 SDK +- .NET 6 SDK ### Сборка После клонирования репозитория идём в папку проекта `Interpreter`. @@ -171,7 +171,7 @@ let s = v2d as string ### Запуск ``` -Interpreter 1.0.0 +Interpreter 1.1.2 Copyright (C) 2022 Interpreter USAGE: Simple interpretation call: