diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index efba52b2..3d9d44dd 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: 6.0.x + dotnet-version: 7.0.x - name: Cache NuGet packages uses: actions/cache@v3 with: @@ -30,7 +30,7 @@ jobs: 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 --filter="Category=Unit" + dotnet test -c Release --no-build -v n --filter="Category=Unit" mkdir coverage-report - name: Code Coverage Summary Report For Merge Request if: github.event_name == 'pull_request' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b3580a01..f16a1013 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: 6.0.x + dotnet-version: 7.0.x - name: Publish run: | mkdir output diff --git a/Interpreter.Lib/BackEnd/AddressedInstructions.cs b/Interpreter.Lib/BackEnd/AddressedInstructions.cs new file mode 100644 index 00000000..49915934 --- /dev/null +++ b/Interpreter.Lib/BackEnd/AddressedInstructions.cs @@ -0,0 +1,69 @@ +using System.Collections; +using Interpreter.Lib.BackEnd.Addresses; +using Interpreter.Lib.BackEnd.Instructions; + +namespace Interpreter.Lib.BackEnd; + +public class AddressedInstructions : IEnumerable +{ + private readonly LinkedList _addresses = new(); + private readonly Dictionary> _addressToNode = new(); + private readonly Dictionary, Instruction> _instructions = new(); + + public Instruction this[IAddress address] => + _instructions[_addressToNode[address]]; + + public void Add(Instruction instruction, string label = null) + { + IAddress newAddress = label is null + ? new HashedAddress(_addresses.Count, instruction.GetHashCode()) + : new Label(label); + instruction.Address = newAddress; + + var last = _addresses.Last; + if (last is not null) + last.Value.Next = newAddress; + + var newNode = _addresses.AddLast(newAddress); + + _addressToNode.Add(newAddress, newNode); + _instructions.Add(newNode, instruction); + } + + public void AddRange(IEnumerable instructions) + { + foreach (var instruction in instructions) + { + var strAddress = instruction.Address?.ToString(); + Add(instruction, + strAddress != null && + strAddress.StartsWith("address") + ? null + : strAddress + ); + } + } + + public void Remove(Instruction instruction) + { + var address = instruction.Address; + var nodeToRemove = _addressToNode[address]; + + var prev = nodeToRemove.Previous; + if (prev is not null) + { + prev.Value.Next = nodeToRemove.Next?.Value; + } + + _addressToNode.Remove(address); + _instructions.Remove(nodeToRemove); + _addresses.Remove(nodeToRemove); + } + + public IEnumerator GetEnumerator() => + _addresses.Select(address => this[address]) + .GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => + GetEnumerator(); +} \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Addresses/HashedAddress.cs b/Interpreter.Lib/BackEnd/Addresses/HashedAddress.cs new file mode 100644 index 00000000..536b2d81 --- /dev/null +++ b/Interpreter.Lib/BackEnd/Addresses/HashedAddress.cs @@ -0,0 +1,31 @@ +namespace Interpreter.Lib.BackEnd.Addresses; + +public class HashedAddress : IAddress +{ + private readonly int _seed1, _seed2; + + public IAddress Next { get; set; } + + public HashedAddress(int seed1, int seed2) => + (_seed1, _seed2) = (seed1, seed2); + + public bool Equals(IAddress other) + { + if (other is HashedAddress simple) + return _seed1 == simple._seed1 && + _seed2 == simple._seed2; + + return false; + } + + public override int GetHashCode() + { + var i1 = _seed1 ^ 17; + var i2 = 31 * _seed2 + i1; + + return HashCode.Combine(i1, i2); + } + + public override string ToString() => + $"address{{{GetHashCode()}}}"; +} \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Addresses/IAddress.cs b/Interpreter.Lib/BackEnd/Addresses/IAddress.cs new file mode 100644 index 00000000..1031c392 --- /dev/null +++ b/Interpreter.Lib/BackEnd/Addresses/IAddress.cs @@ -0,0 +1,8 @@ +namespace Interpreter.Lib.BackEnd.Addresses; + +public interface IAddress : IEquatable +{ + IAddress Next { get; set; } + + int GetHashCode(); +} \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Addresses/Label.cs b/Interpreter.Lib/BackEnd/Addresses/Label.cs new file mode 100644 index 00000000..97674d7a --- /dev/null +++ b/Interpreter.Lib/BackEnd/Addresses/Label.cs @@ -0,0 +1,24 @@ +namespace Interpreter.Lib.BackEnd.Addresses; + +public class Label : IAddress +{ + private readonly string _name; + + public Label(string name) => + _name = name; + + public IAddress Next { get; set; } + + public bool Equals(IAddress other) + { + if (other is Label label) + return _name == label._name; + + return false; + } + + public override int GetHashCode() => + _name.GetHashCode(); + + public override string ToString() => _name; +} \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/AsString.cs b/Interpreter.Lib/BackEnd/Instructions/AsString.cs index 1161a7bd..333eca74 100644 --- a/Interpreter.Lib/BackEnd/Instructions/AsString.cs +++ b/Interpreter.Lib/BackEnd/Instructions/AsString.cs @@ -1,54 +1,53 @@ -using System; using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; using Interpreter.Lib.BackEnd.Values; +using SystemType = System.Type; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class AsString : Simple { - public class AsString : Simple + public AsString(string left, IValue right, int number) : + base(left, (null, right), "", number) { - public AsString(string left, IValue right, int number) : - base(left, (null, right), "", number) - { - } + } - public override int Execute(VirtualMachine vm) - { - var frame = vm.Frames.Peek(); - frame[Left] = JsonSerializer.Serialize( - right.right.Get(frame), - new JsonSerializerOptions - { - WriteIndented = true, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - ReferenceHandler = ReferenceHandler.IgnoreCycles, - Converters = { new DoubleValueWriteConverter() }, - NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals - } - ); + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + frame[Left] = JsonSerializer.Serialize( + right.right.Get(frame), + new JsonSerializerOptions + { + WriteIndented = true, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + ReferenceHandler = ReferenceHandler.IgnoreCycles, + Converters = { new DoubleValueWriteConverter() }, + NumberHandling = JsonNumberHandling.AllowNamedFloatingPointLiterals + } + ); - return Jump(); - } + return Jump(); + } - protected override string ToStringRepresentation() => $"{Left} = {right.right} as string"; + protected override string ToStringRepresentation() => $"{Left} = {right.right} as string"; - [ExcludeFromCodeCoverage] - private class DoubleValueWriteConverter : JsonConverter - { - public override double Read(ref Utf8JsonReader reader, - Type typeToConvert, JsonSerializerOptions options) => - throw new NotImplementedException(); + [ExcludeFromCodeCoverage] + private class DoubleValueWriteConverter : JsonConverter + { + public override double Read(ref Utf8JsonReader reader, + SystemType typeToConvert, JsonSerializerOptions options) => + throw new NotImplementedException(); - public override void Write(Utf8JsonWriter writer, - double value, JsonSerializerOptions options) - { - // ReSharper disable once CompareOfFloatsByEqualityOperator - if (value == Math.Truncate(value)) - writer.WriteNumberValue(Convert.ToInt64(value)); - else - writer.WriteNumberValue(value); - } + public override void Write(Utf8JsonWriter writer, + double value, JsonSerializerOptions options) + { + // ReSharper disable once CompareOfFloatsByEqualityOperator + if (value == Math.Truncate(value)) + writer.WriteNumberValue(Convert.ToInt64(value)); + else + writer.WriteNumberValue(value); } } } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs b/Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs index 69da704b..861a8760 100644 --- a/Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs +++ b/Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs @@ -1,16 +1,15 @@ -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class BeginFunction : Instruction { - public class BeginFunction : Instruction - { - private readonly FunctionInfo _function; + private readonly FunctionInfo _function; - public BeginFunction(int number, FunctionInfo function) : base(number) - { - _function = function; - } + public BeginFunction(int number, FunctionInfo function) : base(number) + { + _function = function; + } - public override int Execute(VirtualMachine vm) => Number + 1; + public override int Execute(VirtualMachine vm) => Number + 1; - protected override string ToStringRepresentation() => $"BeginFunction {_function.CallId()}"; - } + protected override string ToStringRepresentation() => $"BeginFunction {_function.CallId()}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/CallFunction.cs b/Interpreter.Lib/BackEnd/Instructions/CallFunction.cs index dd737278..30f5a128 100644 --- a/Interpreter.Lib/BackEnd/Instructions/CallFunction.cs +++ b/Interpreter.Lib/BackEnd/Instructions/CallFunction.cs @@ -1,51 +1,47 @@ -using System; -using System.Collections.Generic; +namespace Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.BackEnd.Instructions +public class CallFunction : Simple { - public class CallFunction : Simple - { - private readonly FunctionInfo _function; - private readonly int _numberOfArguments; + private readonly FunctionInfo _function; + private readonly int _numberOfArguments; - public CallFunction(FunctionInfo function, int number, int numberOfArguments, string left = null) : - base(left, (null, null), "Call ", number) - { - _function = function; - _numberOfArguments = numberOfArguments + Convert.ToInt32(function.MethodOf != null); - } + public CallFunction(FunctionInfo function, int number, int numberOfArguments, string left = null) : + base(left, (null, null), "Call ", number) + { + _function = function; + _numberOfArguments = numberOfArguments + Convert.ToInt32(function.MethodOf != null); + } - public override int Jump() => _function.Location; + public override int Jump() => _function.Location; - public override int Execute(VirtualMachine vm) - { - var frame = new Frame(Number + 1, vm.Frames.Peek()); + public override int Execute(VirtualMachine vm) + { + var frame = new Frame(Number + 1, vm.Frames.Peek()); - var i = 0; - var args = new List<(string Id, object Value)>(); - while (i < _numberOfArguments) - { - args.Add(vm.Arguments.Pop()); - frame[args[i].Id] = args[i].Value; - i++; - } + var i = 0; + var args = new List<(string Id, object Value)>(); + while (i < _numberOfArguments) + { + args.Add(vm.Arguments.Pop()); + frame[args[i].Id] = args[i].Value; + i++; + } - if (_function.MethodOf != null) + if (_function.MethodOf != null) + { + var obj = (Dictionary) frame[_function.MethodOf]; + foreach (var (key, value) in obj) { - var obj = (Dictionary) frame[_function.MethodOf]; - foreach (var (key, value) in obj) - { - frame[key] = value; - } + frame[key] = value; } - - vm.CallStack.Push(new Call(Number, _function, args, Left)); - vm.Frames.Push(frame); - return _function.Location; } - protected override string ToStringRepresentation() => Left == null - ? $"Call {_function}, {_numberOfArguments}" - : $"{Left} = Call {_function}, {_numberOfArguments}"; + vm.CallStack.Push(new Call(Number, _function, args, Left)); + vm.Frames.Push(frame); + return _function.Location; } + + protected override string ToStringRepresentation() => Left == null + ? $"Call {_function}, {_numberOfArguments}" + : $"{Left} = Call {_function}, {_numberOfArguments}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/CreateArray.cs b/Interpreter.Lib/BackEnd/Instructions/CreateArray.cs index 7f506a93..6dbf2330 100644 --- a/Interpreter.Lib/BackEnd/Instructions/CreateArray.cs +++ b/Interpreter.Lib/BackEnd/Instructions/CreateArray.cs @@ -1,25 +1,22 @@ -using System.Linq; +namespace Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.BackEnd.Instructions +public class CreateArray : Instruction { - public class CreateArray : Instruction - { - private readonly string _id; - private readonly int _size; + private readonly string _id; + private readonly int _size; - public CreateArray(int number, string id, int size) : base(number) - { - _id = id; - _size = size; - } - - public override int Execute(VirtualMachine vm) - { - var frame = vm.Frames.Peek(); - frame[_id] = new object[_size].ToList(); - return Number + 1; - } + public CreateArray(int number, string id, int size) : base(number) + { + _id = id; + _size = size; + } - protected override string ToStringRepresentation() => $"array {_id} = [{_size}]"; + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + frame[_id] = new object[_size].ToList(); + return Number + 1; } + + protected override string ToStringRepresentation() => $"array {_id} = [{_size}]"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/CreateObject.cs b/Interpreter.Lib/BackEnd/Instructions/CreateObject.cs index 65e05eeb..973c5be3 100644 --- a/Interpreter.Lib/BackEnd/Instructions/CreateObject.cs +++ b/Interpreter.Lib/BackEnd/Instructions/CreateObject.cs @@ -1,23 +1,20 @@ -using System.Collections.Generic; +namespace Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.BackEnd.Instructions +public class CreateObject : Instruction { - public class CreateObject : Instruction - { - private readonly string _id; + private readonly string _id; - public CreateObject(int number, string id) : base(number) - { - _id = id; - } - - public override int Execute(VirtualMachine vm) - { - var frame = vm.Frames.Peek(); - frame[_id] = new Dictionary(); - return Number + 1; - } + public CreateObject(int number, string id) : base(number) + { + _id = id; + } - protected override string ToStringRepresentation() => $"object {_id} = {{}}"; + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + frame[_id] = new Dictionary(); + return Number + 1; } + + protected override string ToStringRepresentation() => $"object {_id} = {{}}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs b/Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs index 42121337..8aaf66b0 100644 --- a/Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs +++ b/Interpreter.Lib/BackEnd/Instructions/DotAssignment.cs @@ -1,25 +1,23 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class DotAssignment : Simple { - public class DotAssignment : Simple + public DotAssignment(string left, (IValue left, IValue right) right, int number) : + base(left, right, ".", number) { - public DotAssignment(string left, (IValue left, IValue right) right, int number) : - base(left, right, ".", number) - { - } - - public override int Execute(VirtualMachine vm) - { - var frame = vm.Frames.Peek(); - var obj = (Dictionary) frame[Left]; - var field = (string) right.left.Get(frame) ?? string.Empty; - obj[field] = right.right.Get(frame); - return Number + 1; - } + } - protected override string ToStringRepresentation() => - $"{Left}{@operator}{right.left} = {right.right}"; + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + var obj = (Dictionary) frame[Left]; + var field = (string) right.left.Get(frame) ?? string.Empty; + obj[field] = right.right.Get(frame); + return Number + 1; } + + protected override string ToStringRepresentation() => + $"{Left}{@operator}{right.left} = {right.right}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/Goto.cs b/Interpreter.Lib/BackEnd/Instructions/Goto.cs index 96e03b9a..e633e7e3 100644 --- a/Interpreter.Lib/BackEnd/Instructions/Goto.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Goto.cs @@ -1,20 +1,19 @@ -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class Goto : Instruction { - public class Goto : Instruction - { - protected int jump; + protected int jump; - public Goto(int jump, int number) : base(number) - { - this.jump = jump; - } + public Goto(int jump, int number) : base(number) + { + this.jump = jump; + } - public override int Jump() => jump; + public override int Jump() => jump; - public override int Execute(VirtualMachine vm) => Jump(); + public override int Execute(VirtualMachine vm) => Jump(); - public void SetJump(int newJump) => jump = newJump; + public void SetJump(int newJump) => jump = newJump; - protected override string ToStringRepresentation() => $"Goto {Jump()}"; - } + protected override string ToStringRepresentation() => $"Goto {Jump()}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/Halt.cs b/Interpreter.Lib/BackEnd/Instructions/Halt.cs index 614a7a2f..d9cd0002 100644 --- a/Interpreter.Lib/BackEnd/Instructions/Halt.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Halt.cs @@ -1,19 +1,18 @@ -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class Halt : Instruction { - public class Halt : Instruction + public Halt(int number) : base(number) { - public Halt(int number) : base(number) - { - } - - public override bool End() => true; + } - public override int Execute(VirtualMachine vm) - { - vm.Frames.Pop(); - return -3; - } + public override bool End() => true; - protected override string ToStringRepresentation() => "End"; + public override int Execute(VirtualMachine vm) + { + vm.Frames.Pop(); + return -3; } + + protected override string ToStringRepresentation() => "End"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs b/Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs index 6f275799..64043003 100644 --- a/Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs +++ b/Interpreter.Lib/BackEnd/Instructions/IfNotGoto.cs @@ -1,28 +1,26 @@ -using System; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class IfNotGoto : Goto { - public class IfNotGoto : Goto - { - private readonly IValue _test; + private readonly IValue _test; - public IfNotGoto(IValue test, int jump, int number) : - base(jump, number) - { - _test = test; - } + public IfNotGoto(IValue test, int jump, int number) : + base(jump, number) + { + _test = test; + } - public override int Execute(VirtualMachine vm) + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + if (!Convert.ToBoolean(_test.Get(frame))) { - var frame = vm.Frames.Peek(); - if (!Convert.ToBoolean(_test.Get(frame))) - { - return jump; - } - return Number + 1; + return jump; } - - protected override string ToStringRepresentation() => $"IfNot {_test} Goto {Jump()}"; + return Number + 1; } + + protected override string ToStringRepresentation() => $"IfNot {_test} Goto {Jump()}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs b/Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs index 3865d73e..0d37ed03 100644 --- a/Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs +++ b/Interpreter.Lib/BackEnd/Instructions/IndexAssignment.cs @@ -1,26 +1,23 @@ -using System; -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class IndexAssignment : Simple { - public class IndexAssignment : Simple + public IndexAssignment(string left, (IValue left, IValue right) right, int number) : + base(left, right, "[]", number) { - public IndexAssignment(string left, (IValue left, IValue right) right, int number) : - base(left, right, "[]", number) - { - } - - public override int Execute(VirtualMachine vm) - { - var frame = vm.Frames.Peek(); - var obj = (List) frame[Left]; - var index = Convert.ToInt32(right.left.Get(frame)); - obj[index] = right.right.Get(frame); - return Number + 1; - } + } - protected override string ToStringRepresentation() => - $"{Left}[{right.left}] = {right.right}"; + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + var obj = (List) frame[Left]; + var index = Convert.ToInt32(right.left.Get(frame)); + obj[index] = right.right.Get(frame); + return Number + 1; } + + protected override string ToStringRepresentation() => + $"{Left}[{right.left}] = {right.right}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/Instruction.cs b/Interpreter.Lib/BackEnd/Instructions/Instruction.cs index 06bf49ef..ebd71337 100644 --- a/Interpreter.Lib/BackEnd/Instructions/Instruction.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Instruction.cs @@ -1,24 +1,25 @@ -using System; +using Interpreter.Lib.BackEnd.Addresses; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public abstract class Instruction : IComparable { - public abstract class Instruction : IComparable - { - public int Number { get; } + public int Number { get; } + + public IAddress Address { get; set; } - protected Instruction(int number) => - Number = number; + protected Instruction(int number) => + Number = number; - public virtual int Jump() => Number + 1; + public virtual int Jump() => Number + 1; - public virtual bool End() => false; + public virtual bool End() => false; - public abstract int Execute(VirtualMachine vm); + public abstract int Execute(VirtualMachine vm); - public int CompareTo(Instruction other) => Number.CompareTo(other.Number); + public int CompareTo(Instruction other) => Number.CompareTo(other.Number); - protected abstract string ToStringRepresentation(); + protected abstract string ToStringRepresentation(); - public override string ToString() => $"{Number}: {ToStringRepresentation()}"; - } + public override string ToString() => $"{Number}: {ToStringRepresentation()}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/Print.cs b/Interpreter.Lib/BackEnd/Instructions/Print.cs index 934a44dd..6fb587bb 100644 --- a/Interpreter.Lib/BackEnd/Instructions/Print.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Print.cs @@ -1,22 +1,21 @@ using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class Print : Instruction { - public class Print : Instruction - { - private readonly IValue _value; + private readonly IValue _value; - public Print(int number, IValue value) : base(number) - { - _value = value; - } - - public override int Execute(VirtualMachine vm) - { - vm.Writer.WriteLine(_value.Get(vm.Frames.Peek())); - return Number + 1; - } + public Print(int number, IValue value) : base(number) + { + _value = value; + } - protected override string ToStringRepresentation() => $"Print {_value}"; + public override int Execute(VirtualMachine vm) + { + vm.Writer.WriteLine(_value.Get(vm.Frames.Peek())); + return Number + 1; } + + protected override string ToStringRepresentation() => $"Print {_value}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/PushParameter.cs b/Interpreter.Lib/BackEnd/Instructions/PushParameter.cs index 97358e4c..bdacc41e 100644 --- a/Interpreter.Lib/BackEnd/Instructions/PushParameter.cs +++ b/Interpreter.Lib/BackEnd/Instructions/PushParameter.cs @@ -1,28 +1,27 @@ using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions -{ - public class PushParameter : Instruction - { - private readonly string _parameter; - private readonly IValue _value; +namespace Interpreter.Lib.BackEnd.Instructions; - public PushParameter( - int number, - string parameter, - IValue value - ) : base(number) - { - _parameter = parameter; - _value = value; - } +public class PushParameter : Instruction +{ + private readonly string _parameter; + private readonly IValue _value; - public override int Execute(VirtualMachine vm) - { - vm.Arguments.Push((_parameter, _value.Get(vm.Frames.Peek()))); - return Number + 1; - } + public PushParameter( + int number, + string parameter, + IValue value + ) : base(number) + { + _parameter = parameter; + _value = value; + } - protected override string ToStringRepresentation() => $"PushParameter {_parameter} = {_value}"; + public override int Execute(VirtualMachine vm) + { + vm.Arguments.Push((_parameter, _value.Get(vm.Frames.Peek()))); + return Number + 1; } + + protected override string ToStringRepresentation() => $"PushParameter {_parameter} = {_value}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs b/Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs index 11f65e17..e933855e 100644 --- a/Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs +++ b/Interpreter.Lib/BackEnd/Instructions/RemoveFromArray.cs @@ -1,29 +1,26 @@ -using System; -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class RemoveFromArray : Instruction { - public class RemoveFromArray : Instruction - { - private readonly string _id; - private readonly IValue _index; + private readonly string _id; + private readonly IValue _index; - public RemoveFromArray(int number, string id, IValue index) : base(number) - { - _id = id; - _index = index; - } - - public override int Execute(VirtualMachine vm) - { - var frame = vm.Frames.Peek(); - var list = (List) frame[_id]; - list.RemoveAt(Convert.ToInt32(_index.Get(frame))); - return Number + 1; - } + public RemoveFromArray(int number, string id, IValue index) : base(number) + { + _id = id; + _index = index; + } - protected override string ToStringRepresentation() => - $"RemoveFrom {_id} at {_index}"; + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + var list = (List) frame[_id]; + list.RemoveAt(Convert.ToInt32(_index.Get(frame))); + return Number + 1; } + + protected override string ToStringRepresentation() => + $"RemoveFrom {_id} at {_index}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/Return.cs b/Interpreter.Lib/BackEnd/Instructions/Return.cs index b1355aaa..0a9b3966 100644 --- a/Interpreter.Lib/BackEnd/Instructions/Return.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Return.cs @@ -1,40 +1,38 @@ using System.Collections; -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class Return : Instruction, IEnumerable { - public class Return : Instruction, IEnumerable - { - private readonly IValue _value; - private readonly List _callers = new(); + private readonly IValue _value; + private readonly List _callers = new(); - public int FunctionStart { get; } + public int FunctionStart { get; } - public Return(int functionStart, int number, IValue value = null) : base(number) - { - _value = value; - FunctionStart = functionStart; - } + public Return(int functionStart, int number, IValue value = null) : base(number) + { + _value = value; + FunctionStart = functionStart; + } - public void AddCaller(int caller) => _callers.Add(caller); + public void AddCaller(int caller) => _callers.Add(caller); - public override int Execute(VirtualMachine vm) + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Pop(); + var call = vm.CallStack.Pop(); + if (call.Where != null && _value != null) { - var frame = vm.Frames.Pop(); - var call = vm.CallStack.Pop(); - if (call.Where != null && _value != null) - { - vm.Frames.Peek()[call.Where] = _value.Get(frame); - } - - return frame.ReturnAddress; + vm.Frames.Peek()[call.Where] = _value.Get(frame); } - public IEnumerator GetEnumerator() => _callers.GetEnumerator(); + return frame.ReturnAddress; + } + + public IEnumerator GetEnumerator() => _callers.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - protected override string ToStringRepresentation() => $"Return{(_value != null ? $" {_value}" : "")}"; - } + protected override string ToStringRepresentation() => $"Return{(_value != null ? $" {_value}" : "")}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Instructions/Simple.cs b/Interpreter.Lib/BackEnd/Instructions/Simple.cs index d587132b..8ac1b483 100644 --- a/Interpreter.Lib/BackEnd/Instructions/Simple.cs +++ b/Interpreter.Lib/BackEnd/Instructions/Simple.cs @@ -1,94 +1,90 @@ -using System; -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Instructions +namespace Interpreter.Lib.BackEnd.Instructions; + +public class Simple : Instruction { - public class Simple : Instruction - { - public string Left { get; set; } + public string Left { get; set; } - protected (IValue left, IValue right) right; - protected readonly string @operator; + protected (IValue left, IValue right) right; + protected readonly string @operator; - public Simple( - string left, - (IValue left, IValue right) right, - string @operator, - int number - ) : - base(number) - { - Left = left; - this.right = right; - this.@operator = @operator; - } + public Simple( + string left, + (IValue left, IValue right) right, + string @operator, + int number + ) : + base(number) + { + Left = left; + this.right = right; + this.@operator = @operator; + } - public IValue Source => right.right; + public IValue Source => right.right; - public bool Assignment => @operator == ""; + public bool Assignment => @operator == ""; - public override int Execute(VirtualMachine vm) + public override int Execute(VirtualMachine vm) + { + var frame = vm.Frames.Peek(); + if (right.left == null) { - var frame = vm.Frames.Peek(); - if (right.left == null) + var value = right.right.Get(frame); + frame[Left] = @operator switch { - var value = right.right.Get(frame); - frame[Left] = @operator switch - { - "-" => -Convert.ToDouble(value), - "!" => !Convert.ToBoolean(value), - "~" => ((List) value).Count, - "" => value, - _ => throw new NotImplementedException() - }; - } - else + "-" => -Convert.ToDouble(value), + "!" => !Convert.ToBoolean(value), + "~" => ((List) value).Count, + "" => value, + _ => throw new NotImplementedException() + }; + } + else + { + object lValue = right.left.Get(frame), rValue = right.right.Get(frame); + frame[Left] = @operator switch { - object lValue = right.left.Get(frame), rValue = right.right.Get(frame); - frame[Left] = @operator switch - { - "+" when lValue is string => lValue.ToString() + rValue, - "+" => Convert.ToDouble(lValue) + Convert.ToDouble(rValue), - "-" => Convert.ToDouble(lValue) - Convert.ToDouble(rValue), - "*" => Convert.ToDouble(lValue) * Convert.ToDouble(rValue), - "/" => Convert.ToDouble(lValue) / Convert.ToDouble(rValue), - "%" => Convert.ToDouble(lValue) % Convert.ToDouble(rValue), - "||" => Convert.ToBoolean(lValue) || Convert.ToBoolean(rValue), - "&&" => Convert.ToBoolean(lValue) && Convert.ToBoolean(rValue), - "==" => Equals(lValue, rValue), - "!=" => !Equals(lValue, rValue), - ">" => Convert.ToDouble(lValue) > Convert.ToDouble(rValue), - ">=" => Convert.ToDouble(lValue) >= Convert.ToDouble(rValue), - "<" => Convert.ToDouble(lValue) < Convert.ToDouble(rValue), - "<=" => Convert.ToDouble(lValue) <= Convert.ToDouble(rValue), - "." => ((Dictionary) lValue)[rValue.ToString()!], - "[]" => ((List) lValue)[Convert.ToInt32(rValue)], - "++" => ((List) lValue).Concat((List) rValue).ToList(), - _ => throw new NotImplementedException() - }; - } - if (vm.CallStack.Any()) + "+" when lValue is string => lValue.ToString() + rValue, + "+" => Convert.ToDouble(lValue) + Convert.ToDouble(rValue), + "-" => Convert.ToDouble(lValue) - Convert.ToDouble(rValue), + "*" => Convert.ToDouble(lValue) * Convert.ToDouble(rValue), + "/" => Convert.ToDouble(lValue) / Convert.ToDouble(rValue), + "%" => Convert.ToDouble(lValue) % Convert.ToDouble(rValue), + "||" => Convert.ToBoolean(lValue) || Convert.ToBoolean(rValue), + "&&" => Convert.ToBoolean(lValue) && Convert.ToBoolean(rValue), + "==" => Equals(lValue, rValue), + "!=" => !Equals(lValue, rValue), + ">" => Convert.ToDouble(lValue) > Convert.ToDouble(rValue), + ">=" => Convert.ToDouble(lValue) >= Convert.ToDouble(rValue), + "<" => Convert.ToDouble(lValue) < Convert.ToDouble(rValue), + "<=" => Convert.ToDouble(lValue) <= Convert.ToDouble(rValue), + "." => ((Dictionary) lValue)[rValue.ToString()!], + "[]" => ((List) lValue)[Convert.ToInt32(rValue)], + "++" => ((List) lValue).Concat((List) rValue).ToList(), + _ => throw new NotImplementedException() + }; + } + if (vm.CallStack.Any()) + { + var call = vm.CallStack.Peek(); + var methodOf = call.To.MethodOf; + if (methodOf != null) { - var call = vm.CallStack.Peek(); - var methodOf = call.To.MethodOf; - if (methodOf != null) + var methodOwner = (Dictionary) frame[methodOf]; + if (methodOwner.ContainsKey(Left)) { - var methodOwner = (Dictionary) frame[methodOf]; - if (methodOwner.ContainsKey(Left)) - { - methodOwner[Left] = frame[Left]; - } + methodOwner[Left] = frame[Left]; } } - - return Jump(); } - protected override string ToStringRepresentation() => - right.left == null - ? $"{Left} = {@operator}{right.right}" - : $"{Left} = {right.left} {@operator} {right.right}"; + return Jump(); } + + protected override string ToStringRepresentation() => + right.left == null + ? $"{Left} = {@operator}{right.right}" + : $"{Left} = {right.left} {@operator} {right.right}"; } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Values/Constant.cs b/Interpreter.Lib/BackEnd/Values/Constant.cs index 70c87341..bba39f9b 100644 --- a/Interpreter.Lib/BackEnd/Values/Constant.cs +++ b/Interpreter.Lib/BackEnd/Values/Constant.cs @@ -1,28 +1,27 @@ -namespace Interpreter.Lib.BackEnd.Values +namespace Interpreter.Lib.BackEnd.Values; + +public class Constant : IValue { - public class Constant : IValue - { - private readonly object _value; - private readonly string _representation; + private readonly object _value; + private readonly string _representation; - public Constant(object value, string representation) - { - _value = value; - _representation = representation; - } + public Constant(object value, string representation) + { + _value = value; + _representation = representation; + } - public object Get(Frame frame) => _value; + public object Get(Frame frame) => _value; - public override string ToString() => _representation; + public override string ToString() => _representation; - public bool Equals(IValue other) + public bool Equals(IValue other) + { + if (other is Constant that) { - if (other is Constant that) - { - return Equals(_value, that._value); - } - - return false; + return Equals(_value, that._value); } + + return false; } } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Values/IValue.cs b/Interpreter.Lib/BackEnd/Values/IValue.cs index 06255e67..11bd4a39 100644 --- a/Interpreter.Lib/BackEnd/Values/IValue.cs +++ b/Interpreter.Lib/BackEnd/Values/IValue.cs @@ -1,9 +1,6 @@ -using System; +namespace Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.BackEnd.Values +public interface IValue : IEquatable { - public interface IValue : IEquatable - { - object Get(Frame frame); - } + object Get(Frame frame); } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/Values/Name.cs b/Interpreter.Lib/BackEnd/Values/Name.cs index 7c01b685..9558c340 100644 --- a/Interpreter.Lib/BackEnd/Values/Name.cs +++ b/Interpreter.Lib/BackEnd/Values/Name.cs @@ -1,26 +1,25 @@ -namespace Interpreter.Lib.BackEnd.Values +namespace Interpreter.Lib.BackEnd.Values; + +public class Name : IValue { - public class Name : IValue - { - private readonly string _id; + private readonly string _id; - public Name(string id) - { - _id = id; - } + public Name(string id) + { + _id = id; + } - public object Get(Frame frame) => frame[_id]; + public object Get(Frame frame) => frame[_id]; - public override string ToString() => _id; + public override string ToString() => _id; - public bool Equals(IValue other) + public bool Equals(IValue other) + { + if (other is Name that) { - if (other is Name that) - { - return _id == that._id; - } - - return false; + return _id == that._id; } + + return false; } } \ No newline at end of file diff --git a/Interpreter.Lib/BackEnd/VirtualMachine.cs b/Interpreter.Lib/BackEnd/VirtualMachine.cs index b5ba207c..a88c5565 100644 --- a/Interpreter.Lib/BackEnd/VirtualMachine.cs +++ b/Interpreter.Lib/BackEnd/VirtualMachine.cs @@ -1,79 +1,74 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.BackEnd +namespace Interpreter.Lib.BackEnd; + +public record VirtualMachine( + Stack CallStack, Stack Frames, + Stack<(string Id, object Value)> Arguments, + TextWriter Writer +) { - 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) { - public VirtualMachine() : - this(new(), new(), new(), Console.Out) { } + Frames.Push(new Frame()); - public void Run(List instructions) + var address = 0; + while (!instructions[address].End()) { - 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); + 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 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 record FunctionInfo(string Id, int Location = 0, string MethodOf = null) +{ + public int Location { get; set; } = Location; - public string MethodOf { get; set; } = MethodOf; + public string MethodOf { get; set; } = MethodOf; - public string CallId() => - MethodOf == null - ? Id - : $"{MethodOf}.{Id}"; + public string CallId() => + MethodOf == null + ? Id + : $"{MethodOf}.{Id}"; - public override string ToString() => - $"({Location}, {CallId()})"; - } + public override string ToString() => + $"({Location}, {CallId()})"; +} - public class Frame - { - private readonly Dictionary _variables = new(); - private readonly Frame _parentFrame; +public class Frame +{ + private readonly Dictionary _variables = new(); + private readonly Frame _parentFrame; - public int ReturnAddress { get; } + public int ReturnAddress { get; } - public Frame(int returnAddress = 0, Frame parentFrame = null) - { - ReturnAddress = returnAddress; - _parentFrame = parentFrame; - } + 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; - } + 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/FrontEnd/GetTokens/Data/Structure.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/Structure.cs index 2d451106..04a5f964 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/Structure.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/Structure.cs @@ -1,57 +1,54 @@ using System.Collections; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Text; using System.Text.RegularExpressions; using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; -namespace Interpreter.Lib.FrontEnd.GetTokens.Data +namespace Interpreter.Lib.FrontEnd.GetTokens.Data; + +public class Structure : IEnumerable { - public class Structure : IEnumerable + public Structure(List types) { - public Structure(List types) + types.AddRange(new List { - types.AddRange(new List - { - TokenTypeUtils.End, - TokenTypeUtils.Error - }); - types = types - .OrderBy(t => t.Priority) - .ToList(); + TokenTypeUtils.End, + TokenTypeUtils.Error + }); + types = types + .OrderBy(t => t.Priority) + .ToList(); - Types = types - .ToDictionary(x => x.Tag, x => x); - - Regex = new Regex( - string.Join( - '|', - types - .Where(t => !t.EndOfProgram()) - .Select(t => t.GetNamedRegex()) - .ToList() - ) - ); - } - - private Dictionary Types { get; } + Types = types + .ToDictionary(x => x.Tag, x => x); + + Regex = new Regex( + string.Join( + '|', + types + .Where(t => !t.EndOfProgram()) + .Select(t => t.GetNamedRegex()) + .ToList() + ) + ); + } + + private Dictionary Types { get; } - public Regex Regex { get; } + public Regex Regex { get; } - public TokenType FindByTag(string tag) => - Types[tag]; + public TokenType FindByTag(string tag) => + Types[tag]; - public override string ToString() => - new StringBuilder() - .AppendJoin('\n', - Types.Select(x => $"{x.Key} {x.Value.Pattern}") - ).ToString(); + 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(); - } + [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 index 43fd4ed6..0da227fd 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/Token.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/Token.cs @@ -1,59 +1,57 @@ -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 +namespace Interpreter.Lib.FrontEnd.GetTokens.Data; + +[ExcludeFromCodeCoverage] +public record Token(TokenType Type) { - [ExcludeFromCodeCoverage] - public record Token(TokenType Type) - { - public Segment Segment { get; } + public Segment Segment { get; } - public string Value { get; } + public string Value { get; } - public Token(TokenType type, Segment segment, string value) : - this(type) => - (Segment, Value) = (segment, value); + 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.CanIgnore()) displayValue = ""; - return $"{Type} {Segment}: {displayValue}"; - } + public override string ToString() + { + var displayValue = Value; + if (displayValue != null) displayValue = Regex.Replace(Value, "\"", "\\\""); + if (Type.CanIgnore()) displayValue = ""; + return $"{Type} {Segment}: {displayValue}"; } +} - [ExcludeFromCodeCoverage] - public record Segment(Coordinates Start, Coordinates End) - { - public override string ToString() => $"{Start}-{End}"; +[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); - } + public static Segment operator +(Segment left, Segment right) => + new(left.Start, right.End); +} - [ExcludeFromCodeCoverage] - public record Coordinates(int Line, int Column) +[ExcludeFromCodeCoverage] +public record Coordinates(int Line, int Column) +{ + public Coordinates(int absolutePos, IReadOnlyList system) : + this(0, 0) { - 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) + for (var i = 0; i < system.Count; i++) + if (absolutePos <= system[i]) { - (Line, Column) = (system.Count + 1, 1); + var offset = i == 0 ? -1 : system[i - 1]; + (Line, Column) = (i + 1, absolutePos - offset); + break; } - } - public override string ToString() => $"({Line}, {Column})"; + 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 index ea457862..bccc907b 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/EndOfProgramType.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/EndOfProgramType.cs @@ -1,7 +1,6 @@ -namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +internal record EndOfProgramType() : TokenType("EOP", "", int.MaxValue - 1) { - internal record EndOfProgramType() : TokenType("EOP", "", int.MaxValue - 1) - { - public override bool EndOfProgram() => true; - } + 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 index 199ab7c2..da510a76 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/ErrorType.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/ErrorType.cs @@ -1,7 +1,6 @@ -namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +internal record ErrorType() : TokenType("ERROR", @"\S+", int.MaxValue) { - internal record ErrorType() : TokenType("ERROR", @"\S+", int.MaxValue) - { - public override bool Error() => true; - } + public override bool Error() => true; } \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/IgnorableType.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/IgnorableType.cs index 16d595e4..60a3ca59 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/IgnorableType.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/IgnorableType.cs @@ -1,8 +1,7 @@ -namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +public record IgnorableType(string Tag = null, string Pattern = null, int Priority = 0) + : TokenType(Tag, Pattern, Priority) { - public record IgnorableType(string Tag = null, string Pattern = null, int Priority = 0) - : TokenType(Tag, Pattern, Priority) - { - public override bool CanIgnore() => true; - } + public override bool CanIgnore() => 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 index ff588cd3..aacd802f 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenType.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenType.cs @@ -1,15 +1,14 @@ -namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +public record TokenType(string Tag, string Pattern, int Priority) { - public record TokenType(string Tag, string Pattern, int Priority) - { - public virtual bool CanIgnore() => false; + public virtual bool CanIgnore() => false; - public virtual bool EndOfProgram() => false; + public virtual bool EndOfProgram() => false; - public virtual bool Error() => false; + public virtual bool Error() => false; - public string GetNamedRegex() => $"(?<{Tag}>{Pattern})"; + public string GetNamedRegex() => $"(?<{Tag}>{Pattern})"; - public sealed override string ToString() => Tag; - } + public sealed override string ToString() => Tag; } \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs index c14bfbec..8d2c6e6a 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Data/TokenTypes/TokenTypeUtils.cs @@ -1,8 +1,7 @@ -namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes +namespace Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; + +public static class TokenTypeUtils { - public static class TokenTypeUtils - { - public static readonly TokenType End = new EndOfProgramType(); - public static readonly TokenType Error = new ErrorType(); - } + public static readonly TokenType End = new EndOfProgramType(); + public static readonly TokenType Error = new ErrorType(); } \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs b/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs index c087a637..902d7318 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/ILexer.cs @@ -1,12 +1,10 @@ -using System.Collections.Generic; using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.FrontEnd.GetTokens +namespace Interpreter.Lib.FrontEnd.GetTokens; + +public interface ILexer { - public interface ILexer - { - Structure Structure { get; } + Structure Structure { get; } - List GetTokens(string text); - } + 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 index c699f452..224749a7 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/Impl/Lexer.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/Impl/Lexer.cs @@ -1,72 +1,69 @@ 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 = ""; +namespace Interpreter.Lib.FrontEnd.GetTokens.Impl; - public Structure Structure { get; } +public class Lexer : ILexer, IEnumerable +{ + private readonly List _lines = new(); + private string _text = ""; - public Lexer(Structure structure) => - Structure = structure; + public Structure Structure { get; } - public List GetTokens(string text) - { - _text = text; + public Lexer(Structure structure) => + Structure = structure; - _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); - } + public List GetTokens(string text) + { + _text = text; - return this.Where(t => !t.Type.CanIgnore()).ToList(); + _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); } - public IEnumerator GetEnumerator() + return this.Where(t => !t.Type.CanIgnore()).ToList(); + } + + public IEnumerator GetEnumerator() + { + var matches = Structure.Regex.Matches(_text); + foreach (Match match in matches) { - var matches = Structure.Regex.Matches(_text); - foreach (Match match in matches) + foreach (var type in Structure) { - foreach (var type in Structure) - { - var group = match.Groups[type.Tag]; + var group = match.Groups[type.Tag]; - if (!group.Success) continue; + 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); + 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); + if (type.Error()) throw new LexerException(token); - yield return token; - } + yield return token; } - - yield return new Token(TokenTypeUtils.End); } - [ExcludeFromCodeCoverage] - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public override string ToString() => - string.Join('\n', this); + 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 index 60e007ac..c6ff2439 100644 --- a/Interpreter.Lib/FrontEnd/GetTokens/LexerException.cs +++ b/Interpreter.Lib/FrontEnd/GetTokens/LexerException.cs @@ -1,18 +1,16 @@ -using System; using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.FrontEnd.GetTokens +namespace Interpreter.Lib.FrontEnd.GetTokens; + +[Serializable] +public class LexerException : Exception { - [Serializable] - public class LexerException : Exception - { - public LexerException() { } + public LexerException() { } - protected LexerException(string message) : base(message) { } + protected LexerException(string message) : base(message) { } - protected LexerException(string message, Exception inner) : base(message, inner) { } + protected LexerException(string message, Exception inner) : base(message, inner) { } - public LexerException(Token token) : - base($"Unknown token {token}") { } - } + 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 index f91f82c3..4ab21651 100644 --- a/Interpreter.Lib/FrontEnd/TopDownParse/IParser.cs +++ b/Interpreter.Lib/FrontEnd/TopDownParse/IParser.cs @@ -1,9 +1,8 @@ using Interpreter.Lib.IR.Ast; -namespace Interpreter.Lib.FrontEnd.TopDownParse +namespace Interpreter.Lib.FrontEnd.TopDownParse; + +public interface IParser { - public interface IParser - { - IAbstractSyntaxTree TopDownParse(string text); - } + IAbstractSyntaxTree TopDownParse(string text); } \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs index 4263a7ee..34c97b68 100644 --- a/Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs +++ b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/Parser.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; -using System.Linq; using System.Text.RegularExpressions; using Interpreter.Lib.FrontEnd.GetTokens; using Interpreter.Lib.FrontEnd.GetTokens.Data; @@ -16,838 +14,836 @@ 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 +namespace Interpreter.Lib.FrontEnd.TopDownParse.Impl; + +public class Parser : IParser { - public class Parser : IParser + private TokensStream _tokens; + private readonly ILexer _lexer; + + public Parser(ILexer lexer) => + _lexer = lexer; + + private Token Expect(string expectedTag, string expectedValue = null) { - private TokensStream _tokens; - private readonly ILexer _lexer; + var current = _tokens.Current; - public Parser(ILexer lexer) => - _lexer = lexer; + 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, expectedValue, _tokens.Current); - private Token Expect(string expectedTag, string expectedValue = null) + if (CurrentIs(expectedTag) && _tokens.Current.Value == (expectedValue ?? _tokens.Current.Value)) { - var current = _tokens.Current; + _tokens.MoveNext(); + } - 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, expectedValue, _tokens.Current); + return current; + } - if (CurrentIs(expectedTag) && _tokens.Current.Value == (expectedValue ?? _tokens.Current.Value)) - { - _tokens.MoveNext(); - } + private bool CurrentIs(string tag) => + _tokens.Current!.Type == _lexer.Structure.FindByTag(tag); - return current; - } + private bool CurrentIsLiteral() => + CurrentIs("NullLiteral") || + CurrentIs("IntegerLiteral") || + CurrentIs("FloatLiteral") || + CurrentIs("StringLiteral") || + CurrentIs("BooleanLiteral"); - private bool CurrentIs(string tag) => - _tokens.Current!.Type == _lexer.Structure.FindByTag(tag); + private bool CurrentIsKeyword(string keyword) => + CurrentIs("Keyword") && + _tokens.Current!.Value == keyword; - private bool CurrentIsLiteral() => - CurrentIs("NullLiteral") || - CurrentIs("IntegerLiteral") || - CurrentIs("FloatLiteral") || - CurrentIs("StringLiteral") || - CurrentIs("BooleanLiteral"); + private bool CurrentIsOperator(string @operator) => + CurrentIs("Operator") && + _tokens.Current!.Value == @operator; - private bool CurrentIsKeyword(string keyword) => - CurrentIs("Keyword") && - _tokens.Current!.Value == keyword; + public IAbstractSyntaxTree TopDownParse(string text) + { + _tokens = _lexer.GetTokens(text); + + var root = Script(SymbolTableUtils.GetStandardLibrary()); + Expect("EOP"); + return new AbstractSyntaxTree(root); + } - private bool CurrentIsOperator(string @operator) => - CurrentIs("Operator") && - _tokens.Current!.Value == @operator; + private ScriptBody Script(SymbolTable table = null) => + new(StatementList(table ?? new SymbolTable())) + { + SymbolTable = table ?? new SymbolTable() + }; - public IAbstractSyntaxTree TopDownParse(string text) + private IEnumerable StatementList(SymbolTable table) + { + var statementList = new List(); + while ( + CurrentIsKeyword("function") || CurrentIsKeyword("let") || CurrentIsKeyword("const") || + CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || + CurrentIs("LeftCurl") || CurrentIsKeyword("return") || CurrentIsKeyword("break") || + CurrentIsKeyword("continue") || CurrentIsKeyword("if") || CurrentIsKeyword("while") || + CurrentIsKeyword("type") + ) { - _tokens = _lexer.GetTokens(text); - - var root = Script(SymbolTableUtils.GetStandardLibrary()); - Expect("EOP"); - return new AbstractSyntaxTree(root); + statementList.Add(StatementListItem(table)); } - private ScriptBody Script(SymbolTable table = null) => - new(StatementList(table ?? new SymbolTable())) - { - SymbolTable = table ?? new SymbolTable() - }; + return statementList; + } - private IEnumerable StatementList(SymbolTable table) + private StatementListItem StatementListItem(SymbolTable table) + { + if (CurrentIsKeyword("function") || CurrentIsKeyword("let") || CurrentIsKeyword("const")) { - var statementList = new List(); - while ( - CurrentIsKeyword("function") || CurrentIsKeyword("let") || CurrentIsKeyword("const") || - CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || - CurrentIs("LeftCurl") || CurrentIsKeyword("return") || CurrentIsKeyword("break") || - CurrentIsKeyword("continue") || CurrentIsKeyword("if") || CurrentIsKeyword("while") || - CurrentIsKeyword("type") - ) - { - statementList.Add(StatementListItem(table)); - } + return Declaration(table); + } - return statementList; + return Statement(table); + } + + private Statement Statement(SymbolTable table) + { + if (CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || CurrentIsOperator("-") || + CurrentIsOperator("!")) + { + return ExpressionStatement(table); } - private StatementListItem StatementListItem(SymbolTable table) + if (CurrentIs("LeftCurl")) { - if (CurrentIsKeyword("function") || CurrentIsKeyword("let") || CurrentIsKeyword("const")) - { - return Declaration(table); - } + return BlockStatement(table); + } - return Statement(table); + if (CurrentIsKeyword("return")) + { + return ReturnStatement(table); } - private Statement Statement(SymbolTable table) + if (CurrentIsKeyword("break")) { - if (CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || CurrentIsOperator("-") || - CurrentIsOperator("!")) + return new BreakStatement { - return ExpressionStatement(table); - } + Segment = Expect("Keyword", "break").Segment + }; + } - if (CurrentIs("LeftCurl")) + if (CurrentIsKeyword("continue")) + { + return new ContinueStatement { - return BlockStatement(table); - } + Segment = Expect("Keyword", "continue").Segment + }; + } - if (CurrentIsKeyword("return")) - { - return ReturnStatement(table); - } + if (CurrentIsKeyword("if")) + { + return IfStatement(table); + } - if (CurrentIsKeyword("break")) - { - return new BreakStatement - { - Segment = Expect("Keyword", "break").Segment - }; - } + if (CurrentIsKeyword("while")) + { + return WhileStatement(table); + } - if (CurrentIsKeyword("continue")) - { - return new ContinueStatement - { - Segment = Expect("Keyword", "continue").Segment - }; - } + if (CurrentIsKeyword("type")) + { + return TypeStatement(table); + } - if (CurrentIsKeyword("if")) - { - return IfStatement(table); - } + return null; + } - if (CurrentIsKeyword("while")) - { - return WhileStatement(table); - } + private BlockStatement BlockStatement(SymbolTable table) + { + var newTable = new SymbolTable(); + newTable.AddOpenScope(table); - if (CurrentIsKeyword("type")) - { - return TypeStatement(table); - } + Expect("LeftCurl"); + var block = new BlockStatement(StatementList(newTable)) + { + SymbolTable = newTable + }; + Expect("RightCurl"); - return null; - } + return block; + } - private BlockStatement BlockStatement(SymbolTable table) - { - var newTable = new SymbolTable(); - newTable.AddOpenScope(table); + private ExpressionStatement ExpressionStatement(SymbolTable table) + { + return new(Expression(table)); + } - Expect("LeftCurl"); - var block = new BlockStatement(StatementList(newTable)) + private ReturnStatement ReturnStatement(SymbolTable table) + { + var ret = Expect("Keyword", "return"); + if (CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || CurrentIsOperator("-") || + CurrentIsOperator("!") || CurrentIs("LeftCurl") || CurrentIs("LeftBracket")) + { + return new ReturnStatement(Expression(table)) { - SymbolTable = newTable + Segment = ret.Segment, + SymbolTable = table }; - Expect("RightCurl"); - - return block; } - private ExpressionStatement ExpressionStatement(SymbolTable table) + return new ReturnStatement { - return new(Expression(table)); - } + Segment = ret.Segment + }; + } - private ReturnStatement ReturnStatement(SymbolTable table) + private IfStatement IfStatement(SymbolTable table) + { + var token = Expect("Keyword", "if"); + Expect("LeftParen"); + var expr = Expression(table); + Expect("RightParen"); + var then = Statement(table); + if (CurrentIsKeyword("else")) { - var ret = Expect("Keyword", "return"); - if (CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || CurrentIsOperator("-") || - CurrentIsOperator("!") || CurrentIs("LeftCurl") || CurrentIs("LeftBracket")) - { - return new ReturnStatement(Expression(table)) - { - Segment = ret.Segment, - SymbolTable = table - }; - } - - return new ReturnStatement - { - Segment = ret.Segment - }; + Expect("Keyword", "else"); + var @else = Statement(table); + return new IfStatement(expr, then, @else) {SymbolTable = table, Segment = token.Segment}; } - private IfStatement IfStatement(SymbolTable table) - { - var token = Expect("Keyword", "if"); - Expect("LeftParen"); - var expr = Expression(table); - Expect("RightParen"); - var then = Statement(table); - if (CurrentIsKeyword("else")) - { - Expect("Keyword", "else"); - var @else = Statement(table); - return new IfStatement(expr, then, @else) {SymbolTable = table, Segment = token.Segment}; - } + return new IfStatement(expr, then) {SymbolTable = table, Segment = token.Segment}; + } - return new IfStatement(expr, then) {SymbolTable = table, Segment = token.Segment}; + private WhileStatement WhileStatement(SymbolTable table) + { + var token = Expect("Keyword", "while"); + Expect("LeftParen"); + var expr = Expression(table); + Expect("RightParen"); + var stmt = Statement(table); + return new WhileStatement(expr, stmt) {SymbolTable = table, Segment = token.Segment}; + } + + private TypeStatement TypeStatement(SymbolTable table) + { + var typeWord = Expect("Keyword", "type"); + var ident = Expect("Ident"); + Expect("Assign"); + if (CurrentIs("LeftCurl")) + { + table.AddType(new Type(ident.Value)); } + var type = TypeValue(table); + + type.Recursive = type.ToString().Contains(ident.Value); - private WhileStatement WhileStatement(SymbolTable table) + if (type is ObjectType objectType && type.Recursive) { - var token = Expect("Keyword", "while"); - Expect("LeftParen"); - var expr = Expression(table); - Expect("RightParen"); - var stmt = Statement(table); - return new WhileStatement(expr, stmt) {SymbolTable = table, Segment = token.Segment}; + objectType.ResolveSelfReferences(ident.Value); } + table.AddType(type, ident.Value); + + return new TypeStatement(ident.Value, type) + { + Segment = typeWord.Segment, + SymbolTable = table + }; + } - private TypeStatement TypeStatement(SymbolTable table) + private Type TypeValue(SymbolTable table) + { + if (CurrentIs("Ident")) { - var typeWord = Expect("Keyword", "type"); var ident = Expect("Ident"); - Expect("Assign"); - if (CurrentIs("LeftCurl")) + var typeFromTable = table.FindType(ident.Value); + if (typeFromTable == null) { - table.AddType(new Type(ident.Value)); + throw new UnknownIdentifierReference( + new IdentifierReference(ident.Value) + {Segment = ident.Segment} + ); } - var type = TypeValue(table); - - type.Recursive = type.ToString().Contains(ident.Value); - if (type is ObjectType objectType && type.Recursive) - { - objectType.ResolveSelfReferences(ident.Value); - } - table.AddType(type, ident.Value); - - return new TypeStatement(ident.Value, type) - { - Segment = typeWord.Segment, - SymbolTable = table - }; + return WithSuffix(typeFromTable); } - private Type TypeValue(SymbolTable table) + if (CurrentIs("LeftCurl")) { - if (CurrentIs("Ident")) + Expect("LeftCurl"); + var propertyTypes = new List(); + while (CurrentIs("Ident")) { var ident = Expect("Ident"); - var typeFromTable = table.FindType(ident.Value); - if (typeFromTable == null) - { - throw new UnknownIdentifierReference( - new IdentifierReference(ident.Value) - {Segment = ident.Segment} - ); - } - - return WithSuffix(typeFromTable); + Expect("Colon"); + var propType = TypeValue(table); + propertyTypes.Add(new PropertyType(ident.Value, propType)); + Expect("SemiColon"); } - if (CurrentIs("LeftCurl")) - { - Expect("LeftCurl"); - var propertyTypes = new List(); - while (CurrentIs("Ident")) - { - var ident = Expect("Ident"); - Expect("Colon"); - var propType = TypeValue(table); - propertyTypes.Add(new PropertyType(ident.Value, propType)); - Expect("SemiColon"); - } - - Expect("RightCurl"); + Expect("RightCurl"); - return WithSuffix(new ObjectType(propertyTypes)); - } - - if (CurrentIs("LeftParen")) - { - Expect("LeftParen"); - var args = new List(); - while (CurrentIs("Ident") || CurrentIs("LeftCurl") || CurrentIs("LeftParen")) - { - args.Add(TypeValue(table)); - if (!CurrentIs("RightParen")) - { - Expect("Comma"); - } - } - Expect("RightParen"); - Expect("Arrow"); - var returnType = TypeValue(table); - return new FunctionType(returnType, args); - } - - return null; + return WithSuffix(new ObjectType(propertyTypes)); } - private Type WithSuffix(Type baseType) + if (CurrentIs("LeftParen")) { - var type = baseType; - while (CurrentIs("LeftBracket") || CurrentIs("QuestionMark")) + Expect("LeftParen"); + var args = new List(); + while (CurrentIs("Ident") || CurrentIs("LeftCurl") || CurrentIs("LeftParen")) { - if (CurrentIs("LeftBracket")) - { - Expect("LeftBracket"); - Expect("RightBracket"); - type = new ArrayType(type); - } - else if (CurrentIs("QuestionMark")) + args.Add(TypeValue(table)); + if (!CurrentIs("RightParen")) { - Expect("QuestionMark"); - type = new NullableType(type); + Expect("Comma"); } } - - return type; + Expect("RightParen"); + Expect("Arrow"); + var returnType = TypeValue(table); + return new FunctionType(returnType, args); } - private Declaration Declaration(SymbolTable table) + return null; + } + + private Type WithSuffix(Type baseType) + { + var type = baseType; + while (CurrentIs("LeftBracket") || CurrentIs("QuestionMark")) { - if (CurrentIsKeyword("function")) + if (CurrentIs("LeftBracket")) { - return FunctionDeclaration(table); - } - - if (CurrentIsKeyword("let") || CurrentIsKeyword("const")) + Expect("LeftBracket"); + Expect("RightBracket"); + type = new ArrayType(type); + } + else if (CurrentIs("QuestionMark")) { - return LexicalDeclaration(table); + Expect("QuestionMark"); + type = new NullableType(type); } + } + + return type; + } - return null; + private Declaration Declaration(SymbolTable table) + { + if (CurrentIsKeyword("function")) + { + return FunctionDeclaration(table); } - private FunctionDeclaration FunctionDeclaration(SymbolTable table) + if (CurrentIsKeyword("let") || CurrentIsKeyword("const")) { - var newTable = new SymbolTable(); - newTable.AddOpenScope(table); + return LexicalDeclaration(table); + } - Expect("Keyword", "function"); - var ident = Expect("Ident"); + return null; + } - Expect("LeftParen"); - var args = new List(); - if (CurrentIs("Ident")) - { - var arg = Expect("Ident").Value; - Expect("Colon"); - var type = TypeValue(table); - args.Add(new VariableSymbol(arg, type)); - } + private FunctionDeclaration FunctionDeclaration(SymbolTable table) + { + var newTable = new SymbolTable(); + newTable.AddOpenScope(table); - while (CurrentIs("Comma")) - { - Expect("Comma"); - var arg = Expect("Ident").Value; - Expect("Colon"); - var type = TypeValue(table); - args.Add(new VariableSymbol(arg, type)); - } + Expect("Keyword", "function"); + var ident = Expect("Ident"); - Expect("RightParen"); + Expect("LeftParen"); + var args = new List(); + if (CurrentIs("Ident")) + { + var arg = Expect("Ident").Value; + Expect("Colon"); + var type = TypeValue(table); + args.Add(new VariableSymbol(arg, type)); + } - var returnType = TypeUtils.JavaScriptTypes.Void; - if (CurrentIs("Colon")) - { - Expect("Colon"); - returnType = TypeValue(table); - } + while (CurrentIs("Comma")) + { + Expect("Comma"); + var arg = Expect("Ident").Value; + Expect("Colon"); + var type = TypeValue(table); + args.Add(new VariableSymbol(arg, type)); + } - var functionSymbol = - new FunctionSymbol(ident.Value, args, - new FunctionType(returnType, args.Select(x => x.Type)) - ); - table.AddSymbol(functionSymbol); + Expect("RightParen"); - return new FunctionDeclaration(functionSymbol, BlockStatement(newTable)) - { - Segment = ident.Segment, - SymbolTable = newTable - }; + var returnType = TypeUtils.JavaScriptTypes.Void; + if (CurrentIs("Colon")) + { + Expect("Colon"); + returnType = TypeValue(table); } - private LexicalDeclaration LexicalDeclaration(SymbolTable table) + var functionSymbol = + new FunctionSymbol(ident.Value, args, + new FunctionType(returnType, args.Select(x => x.Type)) + ); + table.AddSymbol(functionSymbol); + + return new FunctionDeclaration(functionSymbol, BlockStatement(newTable)) { - var readOnly = CurrentIsKeyword("const"); - Expect("Keyword", readOnly ? "const" : "let"); - var declaration = new LexicalDeclaration(readOnly) - { - SymbolTable = table - }; + Segment = ident.Segment, + SymbolTable = newTable + }; + } - AddToDeclaration(declaration, table); + private LexicalDeclaration LexicalDeclaration(SymbolTable table) + { + var readOnly = CurrentIsKeyword("const"); + Expect("Keyword", readOnly ? "const" : "let"); + var declaration = new LexicalDeclaration(readOnly) + { + SymbolTable = table + }; - while (CurrentIs("Comma")) - { - Expect("Comma"); - AddToDeclaration(declaration, table); - } + AddToDeclaration(declaration, table); - return declaration; + while (CurrentIs("Comma")) + { + Expect("Comma"); + AddToDeclaration(declaration, table); } - private void AddToDeclaration(LexicalDeclaration declaration, SymbolTable table) + return declaration; + } + + private void AddToDeclaration(LexicalDeclaration declaration, SymbolTable table) + { + var ident = Expect("Ident"); + var identRef = new IdentifierReference(ident.Value) { - var ident = Expect("Ident"); - var identRef = new IdentifierReference(ident.Value) - { - SymbolTable = table, - Segment = ident.Segment - }; - AssignmentExpression assignment = null; + SymbolTable = table, + Segment = ident.Segment + }; + AssignmentExpression assignment = null; + if (CurrentIs("Assign")) + { + var assignSegment = Expect("Assign").Segment; + var expression = Expression(table); + assignment = new AssignmentExpression( + new MemberExpression(identRef, null), expression + ) { Segment = assignSegment }; + } + else if (CurrentIs("Colon")) + { + Expect("Colon"); + var type = TypeValue(table); if (CurrentIs("Assign")) { var assignSegment = Expect("Assign").Segment; var expression = Expression(table); assignment = new AssignmentExpression( - new MemberExpression(identRef, null), expression - ) { Segment = assignSegment }; + new MemberExpression(identRef, null), + expression, type) { Segment = assignSegment }; } - else if (CurrentIs("Colon")) + else { - Expect("Colon"); - var type = TypeValue(table); - if (CurrentIs("Assign")) - { - var assignSegment = Expect("Assign").Segment; - var expression = Expression(table); - assignment = new AssignmentExpression( - new MemberExpression(identRef, null), - expression, type) { Segment = assignSegment }; - } - else - { - var expression = new Literal( - type, TypeUtils.GetDefaultValue(type), - label: TypeUtils.GetDefaultValue(type) == null ? "null" : null - ); - assignment = new AssignmentExpression( - new MemberExpression(identRef, null), - expression, type); - } + var expression = new Literal( + type, TypeUtils.GetDefaultValue(type), + label: TypeUtils.GetDefaultValue(type) == null ? "null" : null + ); + assignment = new AssignmentExpression( + new MemberExpression(identRef, null), + expression, type); } - declaration.AddAssignment(assignment); } + declaration.AddAssignment(assignment); + } - private Expression Expression(SymbolTable table) - { - return AssignmentExpression(table); - } + private Expression Expression(SymbolTable table) + { + return AssignmentExpression(table); + } - private Expression AssignmentExpression(SymbolTable table) + private Expression AssignmentExpression(SymbolTable table) + { + var lhs = LeftHandSideExpression(table); + if (CurrentIs("Assign") && !(lhs is CallExpression)) { - var lhs = LeftHandSideExpression(table); - if (CurrentIs("Assign") && !(lhs is CallExpression)) - { - var assign = Expect("Assign"); - var member = lhs is IdentifierReference reference - ? (MemberExpression) reference - : (MemberExpression) lhs; - return new AssignmentExpression(member, AssignmentExpression(table)) - {SymbolTable = table, Segment = assign.Segment}; - } - - return lhs; + var assign = Expect("Assign"); + var member = lhs is IdentifierReference reference + ? (MemberExpression) reference + : (MemberExpression) lhs; + return new AssignmentExpression(member, AssignmentExpression(table)) + {SymbolTable = table, Segment = assign.Segment}; } - private Expression LeftHandSideExpression(SymbolTable table) + return lhs; + } + + private Expression LeftHandSideExpression(SymbolTable table) + { + var expr = CastExpression(table); + if (expr is IdentifierReference identRef) { - var expr = CastExpression(table); - if (expr is IdentifierReference identRef) + if (CurrentIs("LeftParen") || CurrentIs("LeftBracket") || CurrentIs("Dot")) { - if (CurrentIs("LeftParen") || CurrentIs("LeftBracket") || CurrentIs("Dot")) - { - return CallExpression(identRef, table); - } + return CallExpression(identRef, table); } - - return expr; } - private Expression CallExpression(IdentifierReference identRef, SymbolTable table) + return expr; + } + + private Expression CallExpression(IdentifierReference identRef, SymbolTable table) + { + var member = MemberExpression(identRef, table); + if (CurrentIs("LeftParen")) { - var member = MemberExpression(identRef, table); - if (CurrentIs("LeftParen")) + var lp = Expect("LeftParen"); + var expressions = new List(); + if (CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || CurrentIsOperator("-")) { - var lp = Expect("LeftParen"); - var expressions = new List(); - if (CurrentIs("Ident") || CurrentIsLiteral() || CurrentIs("LeftParen") || CurrentIsOperator("-")) - { - expressions.Add(Expression(table)); - } - - while (CurrentIs("Comma")) - { - Expect("Comma"); - expressions.Add(Expression(table)); - } - - Expect("RightParen"); - return new CallExpression(member, expressions) - { - SymbolTable = table, - Segment = lp.Segment - }; + expressions.Add(Expression(table)); } - return member; - } - - private MemberExpression MemberExpression(IdentifierReference identRef, SymbolTable table) - { - var accessChain = new List(); - while (CurrentIs("LeftBracket") || CurrentIs("Dot")) + while (CurrentIs("Comma")) { - Token access; - if (CurrentIs("LeftBracket")) - { - access = Expect("LeftBracket"); - var lb = access.Segment; - var expr = Expression(table); - var rb = Expect("RightBracket").Segment; - accessChain.Add( - new IndexAccess(expr, accessChain.LastOrDefault()) {Segment = lb + rb} - ); - } - else if (CurrentIs("Dot")) - { - access = Expect("Dot"); - var identToken = Expect("Ident"); - var idRef = new IdentifierReference(identToken.Value) - { - Segment = identToken.Segment, - SymbolTable = table - }; - accessChain.Add( - new DotAccess(idRef, accessChain.LastOrDefault()) {Segment = access.Segment} - ); - } + Expect("Comma"); + expressions.Add(Expression(table)); } - - return new MemberExpression(identRef, accessChain.FirstOrDefault()) + + Expect("RightParen"); + return new CallExpression(member, expressions) { - SymbolTable = table + SymbolTable = table, + Segment = lp.Segment }; } - private Expression CastExpression(SymbolTable table) - { - var cond = ConditionalExpression(table); - if (CurrentIsKeyword("as")) - { - var asKeyword = Expect("Keyword", "as"); - var type = TypeValue(table); - return new CastAsExpression(cond, type) {Segment = asKeyword.Segment}; - } - - return cond; - } + return member; + } - private Expression ConditionalExpression(SymbolTable table) + private MemberExpression MemberExpression(IdentifierReference identRef, SymbolTable table) + { + var accessChain = new List(); + while (CurrentIs("LeftBracket") || CurrentIs("Dot")) { - var test = OrExpression(table); - if (CurrentIs("QuestionMark")) + Token access; + if (CurrentIs("LeftBracket")) { - Expect("QuestionMark"); - var consequent = AssignmentExpression(table); - Expect("Colon"); - var alternate = AssignmentExpression(table); - return new ConditionalExpression(test, consequent, alternate); + access = Expect("LeftBracket"); + var lb = access.Segment; + var expr = Expression(table); + var rb = Expect("RightBracket").Segment; + accessChain.Add( + new IndexAccess(expr, accessChain.LastOrDefault()) {Segment = lb + rb} + ); } - - return test; - } - - private Expression OrExpression(SymbolTable table) - { - var left = AndExpression(table); - while (CurrentIsOperator("||")) + else if (CurrentIs("Dot")) { - var op = Expect("Operator"); - var right = AndExpression(table); - left = new BinaryExpression(left, op.Value, right) + access = Expect("Dot"); + var identToken = Expect("Ident"); + var idRef = new IdentifierReference(identToken.Value) { - Segment = op.Segment + Segment = identToken.Segment, + SymbolTable = table }; + accessChain.Add( + new DotAccess(idRef, accessChain.LastOrDefault()) {Segment = access.Segment} + ); } - - return left; } + + return new MemberExpression(identRef, accessChain.FirstOrDefault()) + { + SymbolTable = table + }; + } - private Expression AndExpression(SymbolTable table) + private Expression CastExpression(SymbolTable table) + { + var cond = ConditionalExpression(table); + if (CurrentIsKeyword("as")) { - var left = EqualityExpression(table); - while (CurrentIsOperator("&&")) - { - var op = Expect("Operator"); - var right = EqualityExpression(table); - left = new BinaryExpression(left, op.Value, right) - { - Segment = op.Segment - }; - } + var asKeyword = Expect("Keyword", "as"); + var type = TypeValue(table); + return new CastAsExpression(cond, type) {Segment = asKeyword.Segment}; + } - return left; + return cond; + } + + private Expression ConditionalExpression(SymbolTable table) + { + var test = OrExpression(table); + if (CurrentIs("QuestionMark")) + { + Expect("QuestionMark"); + var consequent = AssignmentExpression(table); + Expect("Colon"); + var alternate = AssignmentExpression(table); + return new ConditionalExpression(test, consequent, alternate); } - private Expression EqualityExpression(SymbolTable table) + return test; + } + + private Expression OrExpression(SymbolTable table) + { + var left = AndExpression(table); + while (CurrentIsOperator("||")) { - var left = RelationExpression(table); - while (CurrentIsOperator("==") || CurrentIsOperator("!=")) + var op = Expect("Operator"); + var right = AndExpression(table); + left = new BinaryExpression(left, op.Value, right) { - var op = Expect("Operator"); - var right = RelationExpression(table); - left = new BinaryExpression(left, op.Value, right) - { - Segment = op.Segment - }; - } - - return left; + Segment = op.Segment + }; } - private Expression RelationExpression(SymbolTable table) + return left; + } + + private Expression AndExpression(SymbolTable table) + { + var left = EqualityExpression(table); + while (CurrentIsOperator("&&")) { - var left = AdditiveExpression(table); - while (CurrentIsOperator(">") || CurrentIsOperator("<") || CurrentIsOperator(">=") || - CurrentIsOperator("<=")) + var op = Expect("Operator"); + var right = EqualityExpression(table); + left = new BinaryExpression(left, op.Value, right) { - var op = Expect("Operator"); - var right = AdditiveExpression(table); - left = new BinaryExpression(left, op.Value, right) - { - Segment = op.Segment - }; - } - - return left; + Segment = op.Segment + }; } - private Expression AdditiveExpression(SymbolTable table) + return left; + } + + private Expression EqualityExpression(SymbolTable table) + { + var left = RelationExpression(table); + while (CurrentIsOperator("==") || CurrentIsOperator("!=")) { - var left = MultiplicativeExpression(table); - while (CurrentIsOperator("+") || CurrentIsOperator("-")) + var op = Expect("Operator"); + var right = RelationExpression(table); + left = new BinaryExpression(left, op.Value, right) { - var op = Expect("Operator"); - var right = MultiplicativeExpression(table); - left = new BinaryExpression(left, op.Value, right) - { - Segment = op.Segment - }; - } - - return left; + Segment = op.Segment + }; } - private Expression MultiplicativeExpression(SymbolTable table) + return left; + } + + private Expression RelationExpression(SymbolTable table) + { + var left = AdditiveExpression(table); + while (CurrentIsOperator(">") || CurrentIsOperator("<") || CurrentIsOperator(">=") || + CurrentIsOperator("<=")) { - var left = UnaryExpression(table); - while (CurrentIsOperator("*") || CurrentIsOperator("/") || CurrentIsOperator("%") - || CurrentIsOperator("++") || CurrentIsOperator("::")) + var op = Expect("Operator"); + var right = AdditiveExpression(table); + left = new BinaryExpression(left, op.Value, right) { - var op = Expect("Operator"); - var right = UnaryExpression(table); - left = new BinaryExpression(left, op.Value, right) - { - Segment = op.Segment - }; - } - - return left; + Segment = op.Segment + }; } - private Expression UnaryExpression(SymbolTable table) + return left; + } + + private Expression AdditiveExpression(SymbolTable table) + { + var left = MultiplicativeExpression(table); + while (CurrentIsOperator("+") || CurrentIsOperator("-")) { - if (CurrentIsOperator("-") || CurrentIsOperator("!") || CurrentIsOperator("~")) + var op = Expect("Operator"); + var right = MultiplicativeExpression(table); + left = new BinaryExpression(left, op.Value, right) { - var op = Expect("Operator"); - return new UnaryExpression(op.Value, UnaryExpression(table)) - { - Segment = op.Segment - }; - } - - return PrimaryExpression(table); + Segment = op.Segment + }; } - private Expression PrimaryExpression(SymbolTable table) + return left; + } + + private Expression MultiplicativeExpression(SymbolTable table) + { + var left = UnaryExpression(table); + while (CurrentIsOperator("*") || CurrentIsOperator("/") || CurrentIsOperator("%") + || CurrentIsOperator("++") || CurrentIsOperator("::")) { - if (CurrentIs("LeftParen")) + var op = Expect("Operator"); + var right = UnaryExpression(table); + left = new BinaryExpression(left, op.Value, right) { - Expect("LeftParen"); - var expr = Expression(table); - Expect("RightParen"); - return expr; - } + Segment = op.Segment + }; + } + + return left; + } - if (CurrentIs("Ident")) + private Expression UnaryExpression(SymbolTable table) + { + if (CurrentIsOperator("-") || CurrentIsOperator("!") || CurrentIsOperator("~")) + { + var op = Expect("Operator"); + return new UnaryExpression(op.Value, UnaryExpression(table)) { - var ident = Expect("Ident"); - var id = new IdentifierReference(ident.Value) - { - Segment = ident.Segment, - SymbolTable = table - }; + Segment = op.Segment + }; + } - return id; - } + return PrimaryExpression(table); + } - if (CurrentIsLiteral()) - { - return Literal(); - } + private Expression PrimaryExpression(SymbolTable table) + { + if (CurrentIs("LeftParen")) + { + Expect("LeftParen"); + var expr = Expression(table); + Expect("RightParen"); + return expr; + } - if (CurrentIs("LeftCurl")) - { - return ObjectLiteral(table); - } - - if (CurrentIs("LeftBracket")) + if (CurrentIs("Ident")) + { + var ident = Expect("Ident"); + var id = new IdentifierReference(ident.Value) { - return ArrayLiteral(table); - } + Segment = ident.Segment, + SymbolTable = table + }; - return null; + return id; } - private Literal Literal() + if (CurrentIsLiteral()) { - var segment = _tokens.Current!.Segment; - if (CurrentIs("StringLiteral")) - { - var str = Expect("StringLiteral"); - return new Literal( - TypeUtils.JavaScriptTypes.String, - Regex.Unescape(str.Value.Trim('"')), - segment, - str.Value - .Replace(@"\", @"\\") - .Replace(@"""", @"\""") - ); - } + return Literal(); + } - return _tokens.Current.Type.Tag switch - { - "NullLiteral" => new Literal(TypeUtils.JavaScriptTypes.Null, - Expect("NullLiteral").Value == "null" ? null : "", segment, "null"), - "IntegerLiteral" => new Literal(TypeUtils.JavaScriptTypes.Number, - double.Parse(Expect("IntegerLiteral").Value), segment), - "FloatLiteral" => new Literal(TypeUtils.JavaScriptTypes.Number, - double.Parse(Expect("FloatLiteral").Value), segment), - "BooleanLiteral" => new Literal(TypeUtils.JavaScriptTypes.Boolean, - bool.Parse(Expect("BooleanLiteral").Value), segment), - _ => new Literal(TypeUtils.JavaScriptTypes.Undefined, new TypeUtils.Undefined()) - }; + if (CurrentIs("LeftCurl")) + { + return ObjectLiteral(table); + } + + if (CurrentIs("LeftBracket")) + { + return ArrayLiteral(table); } - private ObjectLiteral ObjectLiteral(SymbolTable table) + return null; + } + + private Literal Literal() + { + var segment = _tokens.Current!.Segment; + if (CurrentIs("StringLiteral")) + { + var str = Expect("StringLiteral"); + return new Literal( + TypeUtils.JavaScriptTypes.String, + Regex.Unescape(str.Value.Trim('"')), + segment, + str.Value + .Replace(@"\", @"\\") + .Replace(@"""", @"\""") + ); + } + + return _tokens.Current.Type.Tag switch + { + "NullLiteral" => new Literal(TypeUtils.JavaScriptTypes.Null, + Expect("NullLiteral").Value == "null" ? null : "", segment, "null"), + "IntegerLiteral" => new Literal(TypeUtils.JavaScriptTypes.Number, + double.Parse(Expect("IntegerLiteral").Value), segment), + "FloatLiteral" => new Literal(TypeUtils.JavaScriptTypes.Number, + double.Parse(Expect("FloatLiteral").Value), segment), + "BooleanLiteral" => new Literal(TypeUtils.JavaScriptTypes.Boolean, + bool.Parse(Expect("BooleanLiteral").Value), segment), + _ => new Literal(TypeUtils.JavaScriptTypes.Undefined, new TypeUtils.Undefined()) + }; + } + + private ObjectLiteral ObjectLiteral(SymbolTable table) + { + var newTable = new SymbolTable(); + newTable.AddOpenScope(table); + Expect("LeftCurl"); + var properties = new List(); + var methods = new List(); + while (CurrentIs("Ident")) { - var newTable = new SymbolTable(); - newTable.AddOpenScope(table); - Expect("LeftCurl"); - var properties = new List(); - var methods = new List(); - while (CurrentIs("Ident")) + var idToken = Expect("Ident"); + var id = new IdentifierReference(idToken.Value) { - var idToken = Expect("Ident"); - var id = new IdentifierReference(idToken.Value) - { - Segment = idToken.Segment, - SymbolTable = newTable - }; - if (CurrentIs("Colon")) + Segment = idToken.Segment, + SymbolTable = newTable + }; + if (CurrentIs("Colon")) + { + Expect("Colon"); + var expr = Expression(newTable); + properties.Add(new Property(id, expr)); + } + else if (CurrentIs("Arrow")) + { + Expect("Arrow"); + Expect("LeftParen"); + var args = new List(); + while (CurrentIs("Ident")) { + var name = Expect("Ident").Value; Expect("Colon"); - var expr = Expression(newTable); - properties.Add(new Property(id, expr)); - } - else if (CurrentIs("Arrow")) - { - Expect("Arrow"); - Expect("LeftParen"); - var args = new List(); - while (CurrentIs("Ident")) - { - var name = Expect("Ident").Value; - Expect("Colon"); - var type = TypeValue(newTable); - args.Add(new VariableSymbol(name, type)); - if (!CurrentIs("RightParen")) - { - Expect("Comma"); - } - } - Expect("RightParen"); - var returnType = TypeUtils.JavaScriptTypes.Void; - if (CurrentIs("Colon")) + var type = TypeValue(newTable); + args.Add(new VariableSymbol(name, type)); + if (!CurrentIs("RightParen")) { - Expect("Colon"); - returnType = TypeValue(newTable); + Expect("Comma"); } - - var functionSymbol = new FunctionSymbol(idToken.Value, args, - new FunctionType(returnType, args.Select(a => a.Type)) - ); - newTable.AddSymbol(functionSymbol); - var bodyTable = new SymbolTable(); - bodyTable.AddOpenScope(newTable); - methods.Add(new FunctionDeclaration(functionSymbol, BlockStatement(bodyTable)) - { - Segment = idToken.Segment, - SymbolTable = bodyTable - }); + } + Expect("RightParen"); + var returnType = TypeUtils.JavaScriptTypes.Void; + if (CurrentIs("Colon")) + { + Expect("Colon"); + returnType = TypeValue(newTable); } - Expect("SemiColon"); + var functionSymbol = new FunctionSymbol(idToken.Value, args, + new FunctionType(returnType, args.Select(a => a.Type)) + ); + newTable.AddSymbol(functionSymbol); + var bodyTable = new SymbolTable(); + bodyTable.AddOpenScope(newTable); + methods.Add(new FunctionDeclaration(functionSymbol, BlockStatement(bodyTable)) + { + Segment = idToken.Segment, + SymbolTable = bodyTable + }); } - Expect("RightCurl"); - return new ObjectLiteral(properties, methods) - { - SymbolTable = newTable - }; + + Expect("SemiColon"); } + Expect("RightCurl"); + return new ObjectLiteral(properties, methods) + { + SymbolTable = newTable + }; + } - private ArrayLiteral ArrayLiteral(SymbolTable table) + private ArrayLiteral ArrayLiteral(SymbolTable table) + { + var lb = Expect("LeftBracket").Segment; + var expressions = new List(); + while (CurrentIs("Ident") || CurrentIsLiteral() || + CurrentIs("LeftParen") || CurrentIsOperator("-") || + CurrentIsOperator("!") || CurrentIs("LeftCurl") || + CurrentIs("LeftBracket")) { - var lb = Expect("LeftBracket").Segment; - var expressions = new List(); - while (CurrentIs("Ident") || CurrentIsLiteral() || - CurrentIs("LeftParen") || CurrentIsOperator("-") || - CurrentIsOperator("!") || CurrentIs("LeftCurl") || - CurrentIs("LeftBracket")) + expressions.Add(Expression(table)); + if (!CurrentIs("RightBracket")) { - expressions.Add(Expression(table)); - if (!CurrentIs("RightBracket")) - { - Expect("Comma"); - } + Expect("Comma"); } - var rb = Expect("RightBracket").Segment; - return new ArrayLiteral(expressions) {Segment = lb + rb}; } + var rb = Expect("RightBracket").Segment; + return new ArrayLiteral(expressions) {Segment = lb + rb}; } } \ No newline at end of file diff --git a/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs index 1cde5d97..1c232a29 100644 --- a/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs +++ b/Interpreter.Lib/FrontEnd/TopDownParse/Impl/TokensStream.cs @@ -1,30 +1,28 @@ using System.Collections; -using System.Collections.Generic; using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.FrontEnd.TopDownParse.Impl +namespace Interpreter.Lib.FrontEnd.TopDownParse.Impl; + +public class TokensStream : IEnumerator { - public class TokensStream : IEnumerator - { - private readonly IEnumerator _inner; + private readonly IEnumerator _inner; - private TokensStream(IEnumerator enumerator) - { - _inner = enumerator; - _inner.MoveNext(); - } + private TokensStream(IEnumerator enumerator) + { + _inner = enumerator; + _inner.MoveNext(); + } - public bool MoveNext() => _inner.MoveNext(); + public bool MoveNext() => _inner.MoveNext(); - public void Reset() => _inner.Reset(); + public void Reset() => _inner.Reset(); - public Token Current => _inner.Current; + public Token Current => _inner.Current; - object IEnumerator.Current => Current; + object IEnumerator.Current => Current; - public void Dispose() => _inner.Dispose(); + public void Dispose() => _inner.Dispose(); - public static implicit operator TokensStream(List tokens) => - new (tokens.GetEnumerator()); - } + 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 index 74924931..4d9ba3b6 100644 --- a/Interpreter.Lib/FrontEnd/TopDownParse/ParserException.cs +++ b/Interpreter.Lib/FrontEnd/TopDownParse/ParserException.cs @@ -1,20 +1,18 @@ -using System; using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.FrontEnd.TopDownParse +namespace Interpreter.Lib.FrontEnd.TopDownParse; + +[Serializable] +public class ParserException : Exception { - [Serializable] - public class ParserException : Exception - { - public ParserException() { } + public ParserException() { } - protected ParserException(string message) : base(message) { } + protected ParserException(string message) : base(message) { } - protected ParserException(string message, Exception inner) : base(message, inner) { } + 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})") - { - } + 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/GlobalUsings.cs b/Interpreter.Lib/GlobalUsings.cs new file mode 100644 index 00000000..b7489391 --- /dev/null +++ b/Interpreter.Lib/GlobalUsings.cs @@ -0,0 +1,4 @@ +// Global using directives + +global using Expression = Interpreter.Lib.IR.Ast.Nodes.Expressions.Expression; +global using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs b/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs index d8482dbe..15e5f494 100644 --- a/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs +++ b/Interpreter.Lib/IR/Ast/IAbstractSyntaxTree.cs @@ -1,10 +1,8 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.IR.Ast +namespace Interpreter.Lib.IR.Ast; + +public interface IAbstractSyntaxTree { - public interface IAbstractSyntaxTree - { - List GetInstructions(); - } + List GetInstructions(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs b/Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs index 583bdc5a..e64c614e 100644 --- a/Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs +++ b/Interpreter.Lib/IR/Ast/Impl/AbstractSyntaxTree.cs @@ -1,71 +1,68 @@ -using System.Collections.Generic; -using System.Linq; using System.Text; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.IR.Ast.Nodes; using Interpreter.Lib.IR.Ast.Visitors; -namespace Interpreter.Lib.IR.Ast.Impl +namespace Interpreter.Lib.IR.Ast.Impl; + +public class AbstractSyntaxTree : IAbstractSyntaxTree { - public class AbstractSyntaxTree : IAbstractSyntaxTree + private readonly AbstractSyntaxTreeNode _root; + private readonly InstructionProvider _instructionProvider; + + public AbstractSyntaxTree(AbstractSyntaxTreeNode root) { - private readonly AbstractSyntaxTreeNode _root; - private readonly InstructionProvider _instructionProvider; + _root = root; + _instructionProvider = new(); + } - public AbstractSyntaxTree(AbstractSyntaxTreeNode root) - { - _root = root; - _instructionProvider = new(); - } + private void Check() => + GetAllNodes().ToList().ForEach(node => node.SemanticCheck()); - private void Check() => - GetAllNodes().ToList().ForEach(node => node.SemanticCheck()); + private IEnumerable GetAllNodes() => + _root.GetAllNodes(); - private IEnumerable GetAllNodes() => - _root.GetAllNodes(); + public List GetInstructions() + { + //Check(); - public List GetInstructions() + var newResult = _root.Accept(_instructionProvider); + var start = 0; + var result = new List(); + foreach (var node in _root) { - //Check(); - - var newResult = _root.Accept(_instructionProvider); - var start = 0; - var result = new List(); - foreach (var node in _root) - { - var instructions = node.ToInstructions(start); - result.AddRange(instructions); - start += instructions.Count; - } + var instructions = node.ToInstructions(start); + result.AddRange(instructions); + start += instructions.Count; + } - result.Sort(); - result.Add(new Halt(result.Count)); + result.Sort(); + result.Add(new Halt(result.Count)); - var calls = result.OfType().GroupBy(i => i.Jump()); - foreach (var call in calls) + var calls = result.OfType().GroupBy(i => i.Jump()); + foreach (var call in calls) + { + var returns = result.OfType() + .Where(r => r.FunctionStart == call.Key); + foreach (var ret in returns) { - var returns = result.OfType() - .Where(r => r.FunctionStart == call.Key); - foreach (var ret in returns) + foreach (var caller in call) { - foreach (var caller in call) - { - ret.AddCaller(caller.Number + 1); - } + ret.AddCaller(caller.Number + 1); } } - return result; } + return result; + } - public override string ToString() + public override string ToString() + { + var tree = new StringBuilder("digraph ast {\n"); + _root.GetAllNodes().ForEach(node => { - var tree = new StringBuilder("digraph ast {\n"); - _root.GetAllNodes().ForEach(node => - { - tree.Append('\t').Append(node).Append('\n'); - node.ToList().ForEach(child => tree.Append($"\t{node.GetHashCode()}->{child.GetHashCode()}\n")); - }); - return tree.Append("}\n").ToString(); - } + tree.Append('\t').Append(node).Append('\n'); + node.ToList().ForEach(child => tree.Append($"\t{node.GetHashCode()}->{child.GetHashCode()}\n")); + }); + return tree.Append("}\n").ToString(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs b/Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs index 138f2529..36d83aba 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/AbstractSyntaxTreeNode.cs @@ -1,82 +1,79 @@ using System.Collections; -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.FrontEnd.GetTokens.Data; using Interpreter.Lib.IR.Ast.Nodes.Declarations; using Interpreter.Lib.IR.Ast.Visitors; -using Interpreter.Lib.IR.CheckSemantics.Types; using Interpreter.Lib.IR.CheckSemantics.Variables; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.Ast.Nodes +namespace Interpreter.Lib.IR.Ast.Nodes; + +public abstract class AbstractSyntaxTreeNode : + IEnumerable, + IVisitable> { - public abstract class AbstractSyntaxTreeNode : - IEnumerable, - IVisitable> - { - public AbstractSyntaxTreeNode Parent { get; set; } + public AbstractSyntaxTreeNode Parent { get; set; } - public SymbolTable SymbolTable { get; set; } + public SymbolTable SymbolTable { get; set; } - public bool CanEvaluate { get; protected init; } + public bool CanEvaluate { get; protected init; } - public Segment Segment { get; init; } + public Segment Segment { get; init; } - protected AbstractSyntaxTreeNode() - { - Parent = null; - CanEvaluate = false; - } + protected AbstractSyntaxTreeNode() + { + Parent = null; + CanEvaluate = false; + } - internal List GetAllNodes() + internal List GetAllNodes() + { + var result = new List { - var result = new List - { - this - }; - foreach (var child in this) - { - result.AddRange(child.GetAllNodes()); - } - - return result; + this + }; + foreach (var child in this) + { + result.AddRange(child.GetAllNodes()); } - public bool ChildOf() where T : AbstractSyntaxTreeNode + return result; + } + + public bool ChildOf() where T : AbstractSyntaxTreeNode + { + var parent = Parent; + while (parent != null) { - var parent = Parent; - while (parent != null) + if (parent is T) { - if (parent is T) - { - return true; - } - parent = parent.Parent; + return true; } - - return false; + parent = parent.Parent; } - public void SemanticCheck() + return false; + } + + public void SemanticCheck() + { + if (CanEvaluate && !ChildOf()) { - if (CanEvaluate && !ChildOf()) - { - NodeCheck(); - } + NodeCheck(); } + } - internal virtual Type NodeCheck() => null; + internal virtual Type NodeCheck() => null; - public virtual List ToInstructions(int start) => new (); + public virtual List ToInstructions(int start) => new (); - public abstract IEnumerator GetEnumerator(); + public abstract IEnumerator GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - protected abstract string NodeRepresentation(); + protected abstract string NodeRepresentation(); - public virtual List Accept(InstructionProvider visitor)=>new(); + public virtual List Accept(InstructionProvider visitor)=>new(); - public override string ToString() => $"{GetHashCode()} [label=\"{NodeRepresentation()}\"]"; - } + public override string ToString() => $"{GetHashCode()} [label=\"{NodeRepresentation()}\"]"; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs b/Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs index 5c84de73..290db81f 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Declarations/Declaration.cs @@ -1,7 +1,6 @@ -namespace Interpreter.Lib.IR.Ast.Nodes.Declarations +namespace Interpreter.Lib.IR.Ast.Nodes.Declarations; + +public abstract class Declaration : StatementListItem { - public abstract class Declaration : StatementListItem - { - public override bool IsStatement() => false; - } + public override bool IsStatement() => false; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs b/Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs index 8403d6d7..7d578fde 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Declarations/FunctionDeclaration.cs @@ -1,87 +1,84 @@ -using System.Collections.Generic; -using System.Linq; 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.IR.Ast.Nodes.Declarations +namespace Interpreter.Lib.IR.Ast.Nodes.Declarations; + +public class FunctionDeclaration : Declaration { - public class FunctionDeclaration : Declaration - { - private readonly FunctionSymbol _function; + private readonly FunctionSymbol _function; - private readonly BlockStatement _statements; + private readonly BlockStatement _statements; - public FunctionDeclaration(FunctionSymbol function, BlockStatement statements) - { - _function = function; - function.Body = this; + public FunctionDeclaration(FunctionSymbol function, BlockStatement statements) + { + _function = function; + function.Body = this; - _statements = statements; - _statements.Parent = this; - } + _statements = statements; + _statements.Parent = this; + } - public bool HasReturnStatement() => _statements.HasReturnStatement(); + public bool HasReturnStatement() => _statements.HasReturnStatement(); - public void SetArguments(CallExpression call, List expressions) + public void SetArguments(CallExpression call, List expressions) + { + if (_function.Type.Arguments.Count == expressions.Count) { - if (_function.Type.Arguments.Count == expressions.Count) - { - expressions.Select((e, i) => (e, i)).ToList() - .ForEach(pair => + expressions.Select((e, i) => (e, i)).ToList() + .ForEach(pair => + { + var (e, i) = pair; + var eType = e.NodeCheck(); + if (_function.Type.Arguments[i].Equals(eType)) { - var (e, i) = pair; - var eType = e.NodeCheck(); - if (_function.Type.Arguments[i].Equals(eType)) - { - SymbolTable.AddSymbol(_function.Parameters[i]); - } - else throw new WrongTypeOfArgument(e.Segment, _function.Type.Arguments[i], eType); - }); - } - else throw new WrongNumberOfArguments(call.Segment, _function.Parameters.Count, expressions.Count); + SymbolTable.AddSymbol(_function.Parameters[i]); + } + else throw new WrongTypeOfArgument(e.Segment, _function.Type.Arguments[i], eType); + }); } + else throw new WrongNumberOfArguments(call.Segment, _function.Parameters.Count, expressions.Count); + } - public void Clear() - { - _statements.GetAllNodes().ForEach(x => x.SymbolTable?.Clear()); - SymbolTable.Clear(); - } + public void Clear() + { + _statements.GetAllNodes().ForEach(x => x.SymbolTable?.Clear()); + SymbolTable.Clear(); + } - public FunctionSymbol GetSymbol() => _function; + public FunctionSymbol GetSymbol() => _function; - public override IEnumerator GetEnumerator() - { - yield return _statements; - } + public override IEnumerator GetEnumerator() + { + yield return _statements; + } - protected override string NodeRepresentation() => $"function {_function.Id}"; + protected override string NodeRepresentation() => $"function {_function.Id}"; - public override List ToInstructions(int start) + public override List ToInstructions(int start) + { + var instructions = new List(); + if (_statements.Any()) { - var instructions = new List(); - if (_statements.Any()) - { - _function.CallInfo.Location = start + 1; - - var body = new List - { - new BeginFunction(_function.CallInfo.Location, _function.CallInfo) - }; - body.AddRange(_statements.ToInstructions(_function.CallInfo.Location + 1)); - if (!_statements.HasReturnStatement()) - { - body.Add(new Return(_function.CallInfo.Location, body.Last().Number + 1)); - } + _function.CallInfo.Location = start + 1; - instructions.Add(new Goto(body.Last().Number + 1, start)); - - instructions.AddRange(body); + var body = new List + { + new BeginFunction(_function.CallInfo.Location, _function.CallInfo) + }; + body.AddRange(_statements.ToInstructions(_function.CallInfo.Location + 1)); + if (!_statements.HasReturnStatement()) + { + body.Add(new Return(_function.CallInfo.Location, body.Last().Number + 1)); } - return instructions; + instructions.Add(new Goto(body.Last().Number + 1, start)); + + instructions.AddRange(body); } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs b/Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs index 1958e6c2..ad1e15ae 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Declarations/LexicalDeclaration.cs @@ -1,35 +1,33 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.IR.Ast.Nodes.Expressions; using Interpreter.Lib.IR.Ast.Visitors; -namespace Interpreter.Lib.IR.Ast.Nodes.Declarations +namespace Interpreter.Lib.IR.Ast.Nodes.Declarations; + +public class LexicalDeclaration : Declaration { - public class LexicalDeclaration : Declaration - { - public bool Readonly { get; } - public List Assignments { get; } + public bool Readonly { get; } + public List Assignments { get; } - public LexicalDeclaration(bool @readonly) - { - Readonly = @readonly; - Assignments = new(); - } + public LexicalDeclaration(bool @readonly) + { + Readonly = @readonly; + Assignments = new(); + } - public void AddAssignment(AssignmentExpression assignment) - { - assignment.SymbolTable = SymbolTable; - assignment.Parent = this; - Assignments.Add(assignment); - } + public void AddAssignment(AssignmentExpression assignment) + { + assignment.SymbolTable = SymbolTable; + assignment.Parent = this; + Assignments.Add(assignment); + } - public override IEnumerator GetEnumerator() => - Assignments.GetEnumerator(); + public override IEnumerator GetEnumerator() => + Assignments.GetEnumerator(); - protected override string NodeRepresentation() => - Readonly ? "const" : "let"; + protected override string NodeRepresentation() => + Readonly ? "const" : "let"; - public override List Accept(InstructionProvider visitor) => - visitor.Visit(this); - } + public override List Accept(InstructionProvider visitor) => + visitor.Visit(this); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs index 9b1f3dd4..9ffd5e11 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/AccessExpression.cs @@ -1,36 +1,33 @@ -using Interpreter.Lib.IR.CheckSemantics.Types; +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; -namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions +public abstract class AccessExpression : Expression { - public abstract class AccessExpression : Expression - { - public AccessExpression Next { get; private set; } + public AccessExpression Next { get; private set; } - protected AccessExpression(AccessExpression prev) + protected AccessExpression(AccessExpression prev) + { + if (prev != null) { - if (prev != null) - { - Parent = prev; - prev.Next = this; - } + Parent = prev; + prev.Next = this; } + } - public AccessExpression Tail + public AccessExpression Tail + { + get { - get + var head = this; + while (head.HasNext()) { - var head = this; - while (head.HasNext()) - { - head = head.Next; - } - - return head; + head = head.Next; } + + return head; } + } - public abstract Type Check(Type prev); + public abstract Type Check(Type prev); - public bool HasNext() => Next != null; - } + public bool HasNext() => Next != null; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs index 4ba43fce..b2ea92b8 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/DotAccess.cs @@ -1,65 +1,62 @@ -using System.Collections.Generic; 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.IR.Ast.Nodes.Expressions.AccessExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; + +public class DotAccess : AccessExpression { - public class DotAccess : AccessExpression - { - private readonly IdentifierReference _id; + private readonly IdentifierReference _id; - public DotAccess(IdentifierReference id, AccessExpression prev = null) : base(prev) - { - _id = id; - _id.Parent = this; - } + public DotAccess(IdentifierReference id, AccessExpression prev = null) : base(prev) + { + _id = id; + _id.Parent = this; + } - public string Id => _id.Id; + public string Id => _id.Id; - public override Type Check(Type prev) + public override Type Check(Type prev) + { + if (prev is ObjectType objectType) { - if (prev is ObjectType objectType) + var fieldType = objectType[_id.Id]; + if (fieldType != null) { - var fieldType = objectType[_id.Id]; - if (fieldType != null) - { - return HasNext() ? Next.Check(fieldType) : fieldType; - } - - throw new ObjectAccessException(Segment, objectType, _id.Id); + return HasNext() ? Next.Check(fieldType) : fieldType; } - return null; + throw new ObjectAccessException(Segment, objectType, _id.Id); } - public override IEnumerator GetEnumerator() + return null; + } + + public override IEnumerator GetEnumerator() + { + yield return _id; + if (HasNext()) { - yield return _id; - if (HasNext()) - { - yield return Next; - } + yield return Next; } + } - protected override string NodeRepresentation() => "."; + protected override string NodeRepresentation() => "."; - public override List ToInstructions(int start, string temp) + public override List ToInstructions(int start, string temp) + { + if (HasNext()) { - if (HasNext()) - { - var left = "_t" + start; - var nextInstructions = Next.ToInstructions(start + 1, left); - nextInstructions.Insert(0, - new Simple(left, (new Name(temp), new Constant(_id.Id, _id.Id)), ".", start) - ); - return nextInstructions; - } - - return new(); + var left = "_t" + start; + var nextInstructions = Next.ToInstructions(start + 1, left); + nextInstructions.Insert(0, + new Simple(left, (new Name(temp), new Constant(_id.Id, _id.Id)), ".", start) + ); + return nextInstructions; } + + return new(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs index 9116e281..f733a7a1 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AccessExpressions/IndexAccess.cs @@ -1,72 +1,68 @@ -using System; -using System.Collections.Generic; 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.IR.Ast.Nodes.Expressions.AccessExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; + +public class IndexAccess : AccessExpression { - public class IndexAccess : AccessExpression - { - private readonly Expression _expression; + private readonly Expression _expression; - public IndexAccess(Expression expression, AccessExpression prev = null) : base(prev) - { - _expression = expression; - _expression.Parent = this; - } + public IndexAccess(Expression expression, AccessExpression prev = null) : base(prev) + { + _expression = expression; + _expression.Parent = this; + } - public PrimaryExpression Expression => _expression as PrimaryExpression; + public PrimaryExpression Expression => _expression as PrimaryExpression; - public override IEnumerator GetEnumerator() + public override IEnumerator GetEnumerator() + { + yield return _expression; + if (HasNext()) { - yield return _expression; - if (HasNext()) - { - yield return Next; - } + yield return Next; } + } - public override Type Check(Type prev) + public override Type Check(Type prev) + { + if (prev is ArrayType arrayType) { - if (prev is ArrayType arrayType) + var indexType = _expression.NodeCheck(); + if (indexType.Equals(TypeUtils.JavaScriptTypes.Number)) { - var indexType = _expression.NodeCheck(); - if (indexType.Equals(TypeUtils.JavaScriptTypes.Number)) - { - var elemType = arrayType.Type; - return HasNext() ? Next.Check(elemType) : elemType; - } - - throw new ArrayAccessException(Segment, indexType); + var elemType = arrayType.Type; + return HasNext() ? Next.Check(elemType) : elemType; } - return null; + throw new ArrayAccessException(Segment, indexType); } - protected override string NodeRepresentation() => "[]"; + return null; + } + + protected override string NodeRepresentation() => "[]"; - public override List ToInstructions(int start, string temp) + public override List ToInstructions(int start, string temp) + { + if (HasNext()) { - if (HasNext()) + if (_expression is PrimaryExpression prim) { - if (_expression is PrimaryExpression prim) - { - var left = "_t" + start; - var nextInstructions = Next.ToInstructions(start + 1, left); - nextInstructions.Insert(0, - new Simple(left, (new Name(temp), prim.ToValue()), "[]", start) - ); - return nextInstructions; - } - - throw new NotImplementedException(); + var left = "_t" + start; + var nextInstructions = Next.ToInstructions(start + 1, left); + nextInstructions.Insert(0, + new Simple(left, (new Name(temp), prim.ToValue()), "[]", start) + ); + return nextInstructions; } - return new(); + throw new NotImplementedException(); } + + return new(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs index f8e3c5cc..51450aa7 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/AssignmentExpression.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.BackEnd.Values; using Interpreter.Lib.IR.Ast.Nodes.Declarations; @@ -8,181 +5,179 @@ 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 +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class AssignmentExpression : Expression { - public class AssignmentExpression : Expression - { - private readonly MemberExpression _destination; - private readonly Expression _source; - private readonly Type _destinationType; + private readonly MemberExpression _destination; + private readonly Expression _source; + private readonly Type _destinationType; - public AssignmentExpression(MemberExpression destination, Expression source, Type destinationType = null) - { - _destination = destination; - destination.Parent = this; + public AssignmentExpression(MemberExpression destination, Expression source, Type destinationType = null) + { + _destination = destination; + destination.Parent = this; - _source = source; - source.Parent = this; + _source = source; + source.Parent = this; - _destinationType = destinationType; - } + _destinationType = destinationType; + } - internal override Type NodeCheck() + internal override Type NodeCheck() + { + var id = _destination.Id; + var type = _source.NodeCheck(); + if (Parent is LexicalDeclaration declaration) { - var id = _destination.Id; - var type = _source.NodeCheck(); - if (Parent is LexicalDeclaration declaration) + if (declaration.Readonly && type.Equals(TypeUtils.JavaScriptTypes.Undefined)) { - if (declaration.Readonly && type.Equals(TypeUtils.JavaScriptTypes.Undefined)) - { - throw new ConstWithoutInitializer(_destination); - } + throw new ConstWithoutInitializer(_destination); + } - if (SymbolTable.ContainsSymbol(_destination.Id)) - { - throw new DeclarationAlreadyExists(_destination); - } + if (SymbolTable.ContainsSymbol(_destination.Id)) + { + throw new DeclarationAlreadyExists(_destination); + } - if (_destinationType != null && type.Equals(TypeUtils.JavaScriptTypes.Undefined)) - { - type = _destinationType; - } + if (_destinationType != null && type.Equals(TypeUtils.JavaScriptTypes.Undefined)) + { + type = _destinationType; + } - if (_destinationType != null && !_destinationType.Equals(type)) - { - throw new IncompatibleTypesOfOperands(Segment, _destinationType, type); - } + if (_destinationType != null && !_destinationType.Equals(type)) + { + throw new IncompatibleTypesOfOperands(Segment, _destinationType, type); + } - if (_destinationType == null && type.Equals(TypeUtils.JavaScriptTypes.Undefined)) - { - throw new CannotDefineType(Segment); - } + if (_destinationType == null && type.Equals(TypeUtils.JavaScriptTypes.Undefined)) + { + throw new CannotDefineType(Segment); + } - var typeOfSymbol = _destinationType != null && type.Equals(TypeUtils.JavaScriptTypes.Undefined) - ? _destinationType - : type; - if (typeOfSymbol is ObjectType objectTypeOfSymbol) - { - SymbolTable.AddSymbol(new ObjectSymbol(id, objectTypeOfSymbol, declaration.Readonly, _source.SymbolTable) - { - Table = _source.SymbolTable - }); - } - else + var typeOfSymbol = _destinationType != null && type.Equals(TypeUtils.JavaScriptTypes.Undefined) + ? _destinationType + : type; + if (typeOfSymbol is ObjectType objectTypeOfSymbol) + { + SymbolTable.AddSymbol(new ObjectSymbol(id, objectTypeOfSymbol, declaration.Readonly, _source.SymbolTable) { - SymbolTable.AddSymbol(new VariableSymbol(id, typeOfSymbol, declaration.Readonly)); - } + Table = _source.SymbolTable + }); } else { - var symbol = SymbolTable.FindSymbol(id); - if (symbol != null) - { - if (symbol.ReadOnly) - { - throw new AssignmentToConst(_destination); - } - - if (!_destination.NodeCheck().Equals(type)) - { - throw new IncompatibleTypesOfOperands(Segment, symbol.Type, type); - } - } + SymbolTable.AddSymbol(new VariableSymbol(id, typeOfSymbol, declaration.Readonly)); } - - return type; } - - public override List ToInstructions(int start) + else { - var instructions = new List(); - var destInstructions = _destination.ToInstructions(start, _destination.Id); - var srcInstructions = _source.ToInstructions(start + destInstructions.Count, _destination.Id); - - instructions.AddRange(destInstructions); - instructions.AddRange(srcInstructions); - start += instructions.Count; - - if (_source is MemberExpression member && member.Any()) + var symbol = SymbolTable.FindSymbol(id); + if (symbol != null) { - var access = (member.First() as AccessExpression)?.Tail; - var dest = destInstructions.Any() - ? destInstructions.OfType().Last().Left - : _destination.Id; - var src = srcInstructions.Any() - ? srcInstructions.OfType().Last().Left - : member.Id; - var instruction = access switch + if (symbol.ReadOnly) { - DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", start), - IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", start), - _ => throw new NotImplementedException() - }; - instructions.Add(instruction); - start++; - } - - var last = instructions.OfType().LastOrDefault(); - if (last != null) - { - if (_source is AssignmentExpression) - { - instructions.Add(new Simple( - _destination.Id, - (null, new Name(last.Left)), - "", last.Jump() - )); - start++; + throw new AssignmentToConst(_destination); } - else + + if (!_destination.NodeCheck().Equals(type)) { - last.Left = _destination.Id; + throw new IncompatibleTypesOfOperands(Segment, symbol.Type, type); } } + } + + return type; + } + + public override List ToInstructions(int start) + { + var instructions = new List(); + var destInstructions = _destination.ToInstructions(start, _destination.Id); + var srcInstructions = _source.ToInstructions(start + destInstructions.Count, _destination.Id); + + instructions.AddRange(destInstructions); + instructions.AddRange(srcInstructions); + start += instructions.Count; - if (_destination.Any()) + if (_source is MemberExpression member && member.Any()) + { + var access = (member.First() as AccessExpression)?.Tail; + var dest = destInstructions.Any() + ? destInstructions.OfType().Last().Left + : _destination.Id; + var src = srcInstructions.Any() + ? srcInstructions.OfType().Last().Left + : member.Id; + var instruction = access switch { - var access = (_destination.First() as AccessExpression)?.Tail; - var lastIndex = instructions.Count - 1; - last = instructions.OfType().Last(); - if (last.Assignment) - { - instructions.RemoveAt(lastIndex); - start--; - } - else - { - last.Left = "_t" + last.Number; - } + DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", start), + IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", start), + _ => throw new NotImplementedException() + }; + instructions.Add(instruction); + start++; + } - var dest = destInstructions.Any() - ? destInstructions.OfType().Last().Left - : _destination.Id; - var src = !last.Assignment - ? new Name(last.Left) - : last.Source; - Instruction instruction = access switch - { - DotAccess dot => new DotAssignment(dest, (new Constant(dot.Id, @$"\""{dot.Id}\"""), src), start), - IndexAccess index => new IndexAssignment(dest, (index.Expression.ToValue(), src), start), - _ => throw new NotImplementedException() - }; - instructions.Add(instruction); + var last = instructions.OfType().LastOrDefault(); + if (last != null) + { + if (_source is AssignmentExpression) + { + instructions.Add(new Simple( + _destination.Id, + (null, new Name(last.Left)), + "", last.Jump() + )); + start++; + } + else + { + last.Left = _destination.Id; } - - return instructions; } - public override IEnumerator GetEnumerator() + if (_destination.Any()) { - yield return _destination; - yield return _source; + var access = (_destination.First() as AccessExpression)?.Tail; + var lastIndex = instructions.Count - 1; + last = instructions.OfType().Last(); + if (last.Assignment) + { + instructions.RemoveAt(lastIndex); + start--; + } + else + { + last.Left = "_t" + last.Number; + } + + var dest = destInstructions.Any() + ? destInstructions.OfType().Last().Left + : _destination.Id; + var src = !last.Assignment + ? new Name(last.Left) + : last.Source; + Instruction instruction = access switch + { + DotAccess dot => new DotAssignment(dest, (new Constant(dot.Id, @$"\""{dot.Id}\"""), src), start), + IndexAccess index => new IndexAssignment(dest, (index.Expression.ToValue(), src), start), + _ => throw new NotImplementedException() + }; + instructions.Add(instruction); } - protected override string NodeRepresentation() => "="; + return instructions; + } - public override List ToInstructions(int start, string temp) => ToInstructions(start); + public override IEnumerator GetEnumerator() + { + yield return _destination; + yield return _source; } + + protected override string NodeRepresentation() => "="; + + public override List ToInstructions(int start, string temp) => ToInstructions(start); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs index d727d508..3d3963ea 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/BinaryExpression.cs @@ -1,214 +1,209 @@ -using System; -using System.Collections.Generic; -using System.Linq; 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 +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class BinaryExpression : Expression { - public class BinaryExpression : Expression - { - private readonly Expression _left; + private readonly Expression _left; - private readonly string _operator; + private readonly string _operator; - private readonly Expression _right; + private readonly Expression _right; - public BinaryExpression(Expression left, string @operator, Expression right) - { - _left = left; - _left.Parent = this; + public BinaryExpression(Expression left, string @operator, Expression right) + { + _left = left; + _left.Parent = this; - _operator = @operator; + _operator = @operator; - _right = right; - _right.Parent = this; + _right = right; + _right.Parent = this; + } + + internal override Type NodeCheck() + { + var lType = _left.NodeCheck(); + var rType = _right.NodeCheck(); + Type retType = null; + if (_operator != "::" && !lType.Equals(rType)) + { + throw new IncompatibleTypesOfOperands(Segment, lType, rType); } - internal override Type NodeCheck() + switch (_operator) { - var lType = _left.NodeCheck(); - var rType = _right.NodeCheck(); - Type retType = null; - if (_operator != "::" && !lType.Equals(rType)) - { - throw new IncompatibleTypesOfOperands(Segment, lType, rType); - } + case "+": + if (lType.Equals(TypeUtils.JavaScriptTypes.Number)) + { + retType = TypeUtils.JavaScriptTypes.Number; + } + else if (lType.Equals(TypeUtils.JavaScriptTypes.String)) + { + retType = TypeUtils.JavaScriptTypes.String; + } + else throw new UnsupportedOperation(Segment, lType, _operator); + + break; + case "-": + case "*": + case "/": + case "%": + if (lType.Equals(TypeUtils.JavaScriptTypes.Number)) + { + retType = TypeUtils.JavaScriptTypes.Number; + } + else throw new UnsupportedOperation(Segment, lType, _operator); - switch (_operator) - { - case "+": - if (lType.Equals(TypeUtils.JavaScriptTypes.Number)) - { - retType = TypeUtils.JavaScriptTypes.Number; - } - else if (lType.Equals(TypeUtils.JavaScriptTypes.String)) - { - retType = TypeUtils.JavaScriptTypes.String; - } - else throw new UnsupportedOperation(Segment, lType, _operator); - - break; - case "-": - case "*": - case "/": - case "%": - if (lType.Equals(TypeUtils.JavaScriptTypes.Number)) - { - retType = TypeUtils.JavaScriptTypes.Number; - } - else throw new UnsupportedOperation(Segment, lType, _operator); - - break; - case "||": - case "&&": - if (lType.Equals(TypeUtils.JavaScriptTypes.Boolean)) - { - retType = TypeUtils.JavaScriptTypes.Boolean; - } - else throw new UnsupportedOperation(Segment, lType, _operator); - - break; - case "==": - case "!=": + break; + case "||": + case "&&": + if (lType.Equals(TypeUtils.JavaScriptTypes.Boolean)) + { retType = TypeUtils.JavaScriptTypes.Boolean; - break; - case ">": - case ">=": - case "<": - case "<=": - if (lType.Equals(TypeUtils.JavaScriptTypes.Number)) - { - retType = TypeUtils.JavaScriptTypes.Boolean; - } - else throw new UnsupportedOperation(Segment, lType, _operator); - - break; - case "++": - if (lType is ArrayType && rType is ArrayType) - { - retType = lType; - } - else throw new UnsupportedOperation(Segment, lType, _operator); - - break; - case "::": - if (!(lType is ArrayType)) - { - throw new UnsupportedOperation(Segment, lType, _operator); - } - if (rType.Equals(TypeUtils.JavaScriptTypes.Number)) - { - retType = TypeUtils.JavaScriptTypes.Void; - } - else throw new ArrayAccessException(Segment, rType); - - break; - } + } + else throw new UnsupportedOperation(Segment, lType, _operator); + + break; + case "==": + case "!=": + retType = TypeUtils.JavaScriptTypes.Boolean; + break; + case ">": + case ">=": + case "<": + case "<=": + if (lType.Equals(TypeUtils.JavaScriptTypes.Number)) + { + retType = TypeUtils.JavaScriptTypes.Boolean; + } + else throw new UnsupportedOperation(Segment, lType, _operator); - return retType; - } + break; + case "++": + if (lType is ArrayType && rType is ArrayType) + { + retType = lType; + } + else throw new UnsupportedOperation(Segment, lType, _operator); - public override IEnumerator GetEnumerator() - { - yield return _left; - yield return _right; + break; + case "::": + if (!(lType is ArrayType)) + { + throw new UnsupportedOperation(Segment, lType, _operator); + } + if (rType.Equals(TypeUtils.JavaScriptTypes.Number)) + { + retType = TypeUtils.JavaScriptTypes.Void; + } + else throw new ArrayAccessException(Segment, rType); + + break; } - protected override string NodeRepresentation() => _operator; + return retType; + } + + public override IEnumerator GetEnumerator() + { + yield return _left; + yield return _right; + } - public override List ToInstructions(int start) + protected override string NodeRepresentation() => _operator; + + public override List ToInstructions(int start) + { + if (_left is IdentifierReference arr && _right.Primary() && _operator == "::") { - if (_left is IdentifierReference arr && _right.Primary() && _operator == "::") + return new List { - return new List - { - new RemoveFromArray(start, arr.Id, ((PrimaryExpression) _right).ToValue()) - }; - } - - throw new NotImplementedException(); + new RemoveFromArray(start, arr.Id, ((PrimaryExpression) _right).ToValue()) + }; } - public override List ToInstructions(int start, string temp) - { - var instructions = new List(); - (IValue left, IValue right) newRight = (null, null); + throw new NotImplementedException(); + } - var lInstructions = new List(); - var rInstructions = new List(); + public override List ToInstructions(int start, string temp) + { + var instructions = new List(); + (IValue left, IValue right) newRight = (null, null); - if (_left.Primary()) - { - newRight.left = ((PrimaryExpression) _left).ToValue(); - } - else + var lInstructions = new List(); + var rInstructions = new List(); + + if (_left.Primary()) + { + newRight.left = ((PrimaryExpression) _left).ToValue(); + } + else + { + lInstructions.AddRange(_left.ToInstructions(start, temp)); + if (_left is MemberExpression member && member.Any()) { - lInstructions.AddRange(_left.ToInstructions(start, temp)); - if (_left is MemberExpression member && member.Any()) + var i = start + lInstructions.Count; + var dest = "_t" + i; + var src = lInstructions.Any() + ? lInstructions.OfType().Last().Left + : member.Id; + var instruction = member.AccessChain.Tail switch { - var i = start + lInstructions.Count; - var dest = "_t" + i; - var src = lInstructions.Any() - ? lInstructions.OfType().Last().Left - : member.Id; - var instruction = member.AccessChain.Tail switch - { - DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", i), - IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", i), - _ => throw new NotImplementedException() - }; - lInstructions.Add(instruction); - } - newRight.left = new Name(lInstructions.OfType().Last().Left); + DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", i), + IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", i), + _ => throw new NotImplementedException() + }; + lInstructions.Add(instruction); } + newRight.left = new Name(lInstructions.OfType().Last().Left); + } - if (_right.Primary()) - { - newRight.right = ((PrimaryExpression) _right).ToValue(); - } - else + if (_right.Primary()) + { + newRight.right = ((PrimaryExpression) _right).ToValue(); + } + else + { + var c = _left.Primary() + ? start + : lInstructions.Last().Number + 1; + rInstructions.AddRange(_right.ToInstructions(c, temp)); + if (_right is MemberExpression member && member.Any()) { - var c = _left.Primary() - ? start - : lInstructions.Last().Number + 1; - rInstructions.AddRange(_right.ToInstructions(c, temp)); - if (_right is MemberExpression member && member.Any()) + var i = c + rInstructions.Count; + var dest = "_t" + i; + var src = rInstructions.Any() + ? rInstructions.OfType().Last().Left + : member.Id; + var instruction = member.AccessChain.Tail switch { - var i = c + rInstructions.Count; - var dest = "_t" + i; - var src = rInstructions.Any() - ? rInstructions.OfType().Last().Left - : member.Id; - var instruction = member.AccessChain.Tail switch - { - DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", i), - IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", i), - _ => throw new NotImplementedException() - }; - rInstructions.Add(instruction); - } - newRight.right = new Name(rInstructions.OfType().Last().Left); + DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", i), + IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", i), + _ => throw new NotImplementedException() + }; + rInstructions.Add(instruction); } + newRight.right = new Name(rInstructions.OfType().Last().Left); + } - instructions.AddRange(lInstructions); - instructions.AddRange(rInstructions); + instructions.AddRange(lInstructions); + instructions.AddRange(rInstructions); - var number = instructions.Any() ? instructions.Last().Number + 1 : start; + var number = instructions.Any() ? instructions.Last().Number + 1 : start; - instructions.Add - ( - new Simple( - temp + number, - newRight, _operator, number - ) - ); - return instructions; - } + instructions.Add + ( + new Simple( + temp + number, + newRight, _operator, number + ) + ); + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs index 23d17b08..60d46166 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CallExpression.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.BackEnd.Values; using Interpreter.Lib.IR.Ast.Nodes.Expressions.AccessExpressions; @@ -9,192 +6,190 @@ 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 +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class CallExpression : Expression { - public class CallExpression : Expression - { - private readonly MemberExpression _ident; - private readonly List _expressions; + private readonly MemberExpression _ident; + private readonly List _expressions; - public CallExpression(MemberExpression ident, IEnumerable expressions) - { - _ident = ident; - _ident.Parent = this; + public CallExpression(MemberExpression ident, IEnumerable expressions) + { + _ident = ident; + _ident.Parent = this; - _expressions = new List(expressions); - _expressions.ForEach(expr => expr.Parent = this); - } + _expressions = new List(expressions); + _expressions.ForEach(expr => expr.Parent = this); + } - private FunctionSymbol GetFunction() + private FunctionSymbol GetFunction() + { + if (_ident.Any()) { - if (_ident.Any()) + var table = SymbolTable.FindSymbol(_ident.Id).Table; + var chain = _ident.AccessChain; + while (chain.HasNext()) { - var table = SymbolTable.FindSymbol(_ident.Id).Table; - var chain = _ident.AccessChain; - while (chain.HasNext()) + table = chain switch { - table = chain switch - { - DotAccess dot => table.FindSymbol(dot.Id).Table, - IndexAccess => throw new NotImplementedException(), - _ => throw new NotImplementedException() - }; - chain = chain.Next; - } - - return table.FindSymbol(((DotAccess) chain).Id); + DotAccess dot => table.FindSymbol(dot.Id).Table, + IndexAccess => throw new NotImplementedException(), + _ => throw new NotImplementedException() + }; + chain = chain.Next; } - return SymbolTable.FindSymbol(_ident.Id); + return table.FindSymbol(((DotAccess) chain).Id); } - internal override Type NodeCheck() + return SymbolTable.FindSymbol(_ident.Id); + } + + internal override Type NodeCheck() + { + if (_ident.Any()) { - if (_ident.Any()) - { - _ident.NodeCheck(); - } - else - { - IdentifierReference idRef = _ident; - idRef.NodeCheck(); - } + _ident.NodeCheck(); + } + else + { + IdentifierReference idRef = _ident; + idRef.NodeCheck(); + } - var function = GetFunction(); - if (function == null) - { - throw new SymbolIsNotCallable(_ident.Id, Segment); - } + var function = GetFunction(); + if (function == null) + { + throw new SymbolIsNotCallable(_ident.Id, Segment); + } - if (!function.Type.ReturnType.Equals(TypeUtils.JavaScriptTypes.Void)) + if (!function.Type.ReturnType.Equals(TypeUtils.JavaScriptTypes.Void)) + { + if (!function.Body.HasReturnStatement()) { - if (!function.Body.HasReturnStatement()) - { - throw new FunctionWithoutReturnStatement(function.Body.Segment); - } + throw new FunctionWithoutReturnStatement(function.Body.Segment); } + } - function.Body.SetArguments(this, _expressions); + function.Body.SetArguments(this, _expressions); - var block = function.Body.First().GetAllNodes(); - foreach (var node in block) + var block = function.Body.First().GetAllNodes(); + foreach (var node in block) + { + if (node is ReturnStatement retStmt) { - if (node is ReturnStatement retStmt) + var retType = retStmt.NodeCheck(); + if (retType.Equals(function.Type.ReturnType)) { - var retType = retStmt.NodeCheck(); - if (retType.Equals(function.Type.ReturnType)) - { - function.Body.Clear(); - return retType; - } - - throw new WrongReturnType(retStmt.Segment, function.Type.ReturnType, retType); + function.Body.Clear(); + return retType; } - if (node.CanEvaluate && !(node is CallExpression call && call._ident.Id == _ident.Id)) - { - node.NodeCheck(); - } + throw new WrongReturnType(retStmt.Segment, function.Type.ReturnType, retType); } - function.Body.Clear(); - return TypeUtils.JavaScriptTypes.Void; - } - - public override IEnumerator GetEnumerator() - { - var nodes = new List + if (node.CanEvaluate && !(node is CallExpression call && call._ident.Id == _ident.Id)) { - _ident - }; - nodes.AddRange(_expressions); - return nodes.GetEnumerator(); + node.NodeCheck(); + } } - protected override string NodeRepresentation() => "()"; + function.Body.Clear(); + return TypeUtils.JavaScriptTypes.Void; + } - private List Print(int start) + public override IEnumerator GetEnumerator() + { + var nodes = new List { - var instructions = new List(); - var expression = _expressions.First(); - if (!expression.Primary()) - { - instructions.AddRange(expression.ToInstructions(start, "_t")); - instructions.Add(new Print( - instructions.Last().Number + 1, - new Name(instructions.OfType().Last().Left) - )); - } - else - { - instructions.Add(new Print(start, ((PrimaryExpression) expression).ToValue())); - } + _ident + }; + nodes.AddRange(_expressions); + return nodes.GetEnumerator(); + } - return instructions; - } + protected override string NodeRepresentation() => "()"; - public override List ToInstructions(int start) + private List Print(int start) + { + var instructions = new List(); + var expression = _expressions.First(); + if (!expression.Primary()) { - return _ident.Id switch - { - "print" when !_ident.Any() => Print(start), - _ => ToInstructions(start, null) - }; + instructions.AddRange(expression.ToInstructions(start, "_t")); + instructions.Add(new Print( + instructions.Last().Number + 1, + new Name(instructions.OfType().Last().Left) + )); + } + else + { + instructions.Add(new Print(start, ((PrimaryExpression) expression).ToValue())); } - public override List ToInstructions(int start, string temp) + return instructions; + } + + public override List ToInstructions(int start) + { + return _ident.Id switch { - var instructions = new List(); - FunctionSymbol function; - if (!_ident.Any()) - { - function = SymbolTable.FindSymbol(_ident.Id); - } - else - { - function = GetFunction(); - instructions.AddRange(_ident.ToInstructions(start, temp)); - function.CallInfo.MethodOf = instructions.Any() - ? instructions.OfType().Last().Left - : function.CallInfo.MethodOf; - instructions.Add( - new PushParameter( - start + instructions.Count, - "this", new Name(function.CallInfo.MethodOf)) - ); - } - if (function.Body.First().Any()) - { - _expressions.Zip(function.Parameters).ToList<(Expression expr, Symbol param)>() - .ForEach(item => - { - var (expr, symbol) = item; - var paramInstructions = expr.Primary() - ? new List() - : expr.ToInstructions(start, "_t"); - var pushNumber = start + instructions.Count + paramInstructions.Count; - var pushValue = expr.Primary() - ? ((PrimaryExpression) expr).ToValue() - : new Name(paramInstructions.OfType().Last().Left); - paramInstructions.Add( - new PushParameter(pushNumber, symbol.Id, pushValue) - ); - instructions.AddRange(paramInstructions); - }); - var left = temp != null - ? temp + (start + instructions.Count) - : null; - instructions.Add( - new CallFunction( - function.CallInfo, - start + instructions.Count, - function.Parameters.Count, left - )); - } + "print" when !_ident.Any() => Print(start), + _ => ToInstructions(start, null) + }; + } - return instructions; + public override List ToInstructions(int start, string temp) + { + var instructions = new List(); + FunctionSymbol function; + if (!_ident.Any()) + { + function = SymbolTable.FindSymbol(_ident.Id); + } + else + { + function = GetFunction(); + instructions.AddRange(_ident.ToInstructions(start, temp)); + function.CallInfo.MethodOf = instructions.Any() + ? instructions.OfType().Last().Left + : function.CallInfo.MethodOf; + instructions.Add( + new PushParameter( + start + instructions.Count, + "this", new Name(function.CallInfo.MethodOf)) + ); + } + if (function.Body.First().Any()) + { + _expressions.Zip(function.Parameters).ToList<(Expression expr, Symbol param)>() + .ForEach(item => + { + var (expr, symbol) = item; + var paramInstructions = expr.Primary() + ? new List() + : expr.ToInstructions(start, "_t"); + var pushNumber = start + instructions.Count + paramInstructions.Count; + var pushValue = expr.Primary() + ? ((PrimaryExpression) expr).ToValue() + : new Name(paramInstructions.OfType().Last().Left); + paramInstructions.Add( + new PushParameter(pushNumber, symbol.Id, pushValue) + ); + instructions.AddRange(paramInstructions); + }); + var left = temp != null + ? temp + (start + instructions.Count) + : null; + instructions.Add( + new CallFunction( + function.CallInfo, + start + instructions.Count, + function.Parameters.Count, left + )); } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs index b2b7a433..5c9f5503 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/CastAsExpression.cs @@ -1,55 +1,52 @@ -using System.Collections.Generic; -using System.Linq; 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.IR.Ast.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class CastAsExpression : Expression { - public class CastAsExpression : Expression + private readonly Expression _expression; + private readonly Type _cast; + + public CastAsExpression(Expression expression, Type cast) { - private readonly Expression _expression; - private readonly Type _cast; + _expression = expression; + _expression.Parent = this; - public CastAsExpression(Expression expression, Type cast) - { - _expression = expression; - _expression.Parent = this; + _cast = cast; + } - _cast = cast; - } + internal override Type NodeCheck() => + TypeUtils.JavaScriptTypes.String; + + public override IEnumerator GetEnumerator() + { + yield return _expression; + } + + protected override string NodeRepresentation() => $"as {_cast}"; - internal override Type NodeCheck() => - TypeUtils.JavaScriptTypes.String; + public override List ToInstructions(int start, string temp) + { + var instructions = new List(); + var castNumber = start; - public override IEnumerator GetEnumerator() + if (!_expression.Primary()) { - yield return _expression; + instructions.AddRange(_expression.ToInstructions(start, "_t")); + castNumber = instructions.Last().Number + 1; } - protected override string NodeRepresentation() => $"as {_cast}"; + instructions.Add(new AsString( + "_t" + castNumber, + _expression.Primary() + ? ((PrimaryExpression) _expression).ToValue() + : new Name(instructions.OfType().Last().Left), + castNumber + )); - public override List ToInstructions(int start, string temp) - { - var instructions = new List(); - var castNumber = start; - - if (!_expression.Primary()) - { - instructions.AddRange(_expression.ToInstructions(start, "_t")); - castNumber = instructions.Last().Number + 1; - } - - instructions.Add(new AsString( - "_t" + castNumber, - _expression.Primary() - ? ((PrimaryExpression) _expression).ToValue() - : new Name(instructions.OfType().Last().Left), - castNumber - )); - - return instructions; - } + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs index d9cc81d6..8d555a68 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ArrayLiteral.cs @@ -1,76 +1,73 @@ -using System.Collections.Generic; -using System.Linq; 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.IR.Ast.Nodes.Expressions.ComplexLiterals +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals; + +public class ArrayLiteral : Expression { - public class ArrayLiteral : Expression - { - private readonly List _expressions; + private readonly List _expressions; - public ArrayLiteral(IEnumerable expressions) - { - _expressions = new List(expressions); - _expressions.ForEach(expr => expr.Parent = this); - } + public ArrayLiteral(IEnumerable expressions) + { + _expressions = new List(expressions); + _expressions.ForEach(expr => expr.Parent = this); + } - internal override Type NodeCheck() + internal override Type NodeCheck() + { + if (_expressions.Any()) { - if (_expressions.Any()) + var type = _expressions.First().NodeCheck(); + if (_expressions.All(e => e.NodeCheck().Equals(type))) { - var type = _expressions.First().NodeCheck(); - if (_expressions.All(e => e.NodeCheck().Equals(type))) - { - return new ArrayType(type); - } - - throw new WrongArrayLiteralDeclaration(Segment, type); + return new ArrayType(type); } - return TypeUtils.JavaScriptTypes.Undefined; + throw new WrongArrayLiteralDeclaration(Segment, type); } - public override IEnumerator GetEnumerator() => - _expressions.GetEnumerator(); + return TypeUtils.JavaScriptTypes.Undefined; + } - protected override string NodeRepresentation() => "[]"; + public override IEnumerator GetEnumerator() => + _expressions.GetEnumerator(); - public override List ToInstructions(int start, string temp) + protected override string NodeRepresentation() => "[]"; + + public override List ToInstructions(int start, string temp) + { + if (Parent is not AssignmentExpression) + { + temp = "_t" + start; + } + var instructions = new List { - if (Parent is not AssignmentExpression) + new CreateArray(start, temp, _expressions.Count) + }; + var j = 1; + for (var i = 0; i < _expressions.Count; i++) + { + var expr = _expressions[i]; + var index = new Constant(i, i.ToString()); + if (expr is PrimaryExpression prim) { - temp = "_t" + start; + instructions.Add(new IndexAssignment(temp, (index, prim.ToValue()), start + j)); + j++; } - var instructions = new List - { - new CreateArray(start, temp, _expressions.Count) - }; - var j = 1; - for (var i = 0; i < _expressions.Count; i++) + else { - var expr = _expressions[i]; - var index = new Constant(i, i.ToString()); - if (expr is PrimaryExpression prim) - { - instructions.Add(new IndexAssignment(temp, (index, prim.ToValue()), start + j)); - j++; - } - else - { - var propInstructions = expr.ToInstructions(start + j, "_t" + (start + j)); - j += propInstructions.Count; - var left = propInstructions.OfType().Last().Left; - propInstructions.Add(new IndexAssignment(temp, (index, new Name(left)), start + j)); - j++; - instructions.AddRange(propInstructions); - } + var propInstructions = expr.ToInstructions(start + j, "_t" + (start + j)); + j += propInstructions.Count; + var left = propInstructions.OfType().Last().Left; + propInstructions.Add(new IndexAssignment(temp, (index, new Name(left)), start + j)); + j++; + instructions.AddRange(propInstructions); } - - return instructions; } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs index 8ce598a1..4f59bed5 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/ObjectLiteral.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.BackEnd.Values; using Interpreter.Lib.IR.Ast.Nodes.Declarations; @@ -7,80 +5,79 @@ using Interpreter.Lib.IR.CheckSemantics.Types; using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals; + +public class ObjectLiteral : Expression { - public class ObjectLiteral : Expression - { - private readonly List _properties; - private readonly List _methods; + private readonly List _properties; + private readonly List _methods; - public ObjectLiteral(IEnumerable properties, IEnumerable methods) - { - _properties = new List(properties); - _properties.ForEach(prop => prop.Parent = this); + public ObjectLiteral(IEnumerable properties, IEnumerable methods) + { + _properties = new List(properties); + _properties.ForEach(prop => prop.Parent = this); - _methods = new List(methods); - _methods.ForEach(m => m.Parent = this); - } + _methods = new List(methods); + _methods.ForEach(m => m.Parent = this); + } - internal override Type NodeCheck() + internal override Type NodeCheck() + { + var propertyTypes = new List(); + _properties.ForEach(prop => { - var propertyTypes = new List(); - _properties.ForEach(prop => - { - var propType = prop.Expression.NodeCheck(); - propertyTypes.Add(new PropertyType(prop.Id.Id, 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 => - { - var symbol = m.GetSymbol(); - propertyTypes.Add(new PropertyType(symbol.Id, symbol.Type)); - }); - var type = new ObjectType(propertyTypes); - SymbolTable.AddSymbol(new VariableSymbol("this", type, true)); - return type; - } + var propType = prop.Expression.NodeCheck(); + propertyTypes.Add(new PropertyType(prop.Id.Id, 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 => + { + var symbol = m.GetSymbol(); + propertyTypes.Add(new PropertyType(symbol.Id, symbol.Type)); + }); + var type = new ObjectType(propertyTypes); + SymbolTable.AddSymbol(new VariableSymbol("this", type, true)); + return type; + } - public override IEnumerator GetEnumerator() => - _properties.Concat(_methods).GetEnumerator(); + public override IEnumerator GetEnumerator() => + _properties.Concat(_methods).GetEnumerator(); - protected override string NodeRepresentation() => "{}"; + protected override string NodeRepresentation() => "{}"; - public override List ToInstructions(int start, string temp) + public override List ToInstructions(int start, string temp) + { + var instructions = new List(); + _methods.ForEach(method => { - var instructions = new List(); - _methods.ForEach(method => - { - var mInstructions = method.ToInstructions(start); - instructions.AddRange(mInstructions); - start += mInstructions.Count; - }); + var mInstructions = method.ToInstructions(start); + instructions.AddRange(mInstructions); + start += mInstructions.Count; + }); - instructions.Add(new CreateObject(start, temp)); - var i = 1; - foreach (var (id, expr) in _properties) + instructions.Add(new CreateObject(start, temp)); + var i = 1; + foreach (var (id, expr) in _properties) + { + if (expr is PrimaryExpression prim) { - if (expr is PrimaryExpression prim) - { - instructions.Add(new DotAssignment(temp, (new Constant(id, @$"\""{id}\"""), prim.ToValue()), start + i)); - i++; - } - else - { - var propInstructions = expr.ToInstructions(start + i, "_t" + (start + i)); - i += propInstructions.Count; - var left = propInstructions.OfType().Last().Left; - propInstructions.Add(new DotAssignment(temp, (new Constant(id, @$"\""{id}\"""), new Name(left)), start + i)); - i++; - instructions.AddRange(propInstructions); - } + instructions.Add(new DotAssignment(temp, (new Constant(id, @$"\""{id}\"""), prim.ToValue()), start + i)); + i++; + } + else + { + var propInstructions = expr.ToInstructions(start + i, "_t" + (start + i)); + i += propInstructions.Count; + var left = propInstructions.OfType().Last().Left; + propInstructions.Add(new DotAssignment(temp, (new Constant(id, @$"\""{id}\"""), new Name(left)), start + i)); + i++; + instructions.AddRange(propInstructions); } - - return instructions; } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs index d86dd5d2..51681b48 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ComplexLiterals/Property.cs @@ -1,40 +1,38 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; -namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.ComplexLiterals; + +public class Property : Expression { - public class Property : Expression - { - public IdentifierReference Id { get; } - public Expression Expression { get; } + public IdentifierReference Id { get; } + public Expression Expression { get; } - public Property(IdentifierReference id, Expression expression) - { - Id = id; - Id.Parent = this; + public Property(IdentifierReference id, Expression expression) + { + Id = id; + Id.Parent = this; - Expression = expression; - Expression.Parent = this; - } + Expression = expression; + Expression.Parent = this; + } - public void Deconstruct(out string id, out Expression expr) - { - id = Id.Id; - expr = Expression; - } + public void Deconstruct(out string id, out Expression expr) + { + id = Id.Id; + expr = Expression; + } - public override IEnumerator GetEnumerator() - { - yield return Id; - yield return Expression; - } + public override IEnumerator GetEnumerator() + { + yield return Id; + yield return Expression; + } - protected override string NodeRepresentation() => ":"; + protected override string NodeRepresentation() => ":"; - public override List ToInstructions(int start, string temp) - { - throw new System.NotImplementedException(); - } + public override List ToInstructions(int start, string temp) + { + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs index 86d5a800..2eafabaa 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/ConditionalExpression.cs @@ -1,91 +1,88 @@ -using System.Collections.Generic; -using System.Linq; 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.IR.Ast.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class ConditionalExpression : Expression { - public class ConditionalExpression : Expression + private readonly Expression _test, _consequent, _alternate; + + public ConditionalExpression(Expression test, Expression consequent, Expression alternate) { - private readonly Expression _test, _consequent, _alternate; + _test = test; + _consequent = consequent; + _alternate = alternate; - public ConditionalExpression(Expression test, Expression consequent, Expression alternate) - { - _test = test; - _consequent = consequent; - _alternate = alternate; + _test.Parent = this; + _consequent.Parent = this; + _alternate.Parent = this; + } - _test.Parent = this; - _consequent.Parent = this; - _alternate.Parent = this; - } + internal override Type NodeCheck() + { + var tType = _test.NodeCheck(); - internal override Type NodeCheck() + if (tType.Equals(TypeUtils.JavaScriptTypes.Boolean)) { - var tType = _test.NodeCheck(); - - if (tType.Equals(TypeUtils.JavaScriptTypes.Boolean)) + var cType = _consequent.NodeCheck(); + var aType = _alternate.NodeCheck(); + if (cType.Equals(aType)) { - var cType = _consequent.NodeCheck(); - var aType = _alternate.NodeCheck(); - if (cType.Equals(aType)) - { - return cType; - } - - throw new WrongConditionalTypes(_consequent.Segment, cType, _alternate.Segment, aType); + return cType; } - throw new NotBooleanTestExpression(_test.Segment, tType); + throw new WrongConditionalTypes(_consequent.Segment, cType, _alternate.Segment, aType); } - public override IEnumerator GetEnumerator() - { - yield return _test; - yield return _consequent; - yield return _alternate; - } + throw new NotBooleanTestExpression(_test.Segment, tType); + } + + public override IEnumerator GetEnumerator() + { + yield return _test; + yield return _consequent; + yield return _alternate; + } - protected override string NodeRepresentation() => "?:"; + protected override string NodeRepresentation() => "?:"; - public override List ToInstructions(int start, string temp) + public override List ToInstructions(int start, string temp) + { + var instructions = new List(); + IValue ifNotTest; + if (!_test.Primary()) { - var instructions = new List(); - IValue ifNotTest; - if (!_test.Primary()) - { - var testInstructions = _test.ToInstructions(start, "_t"); - ifNotTest = new Name(testInstructions.OfType().Last().Left); - instructions.AddRange(testInstructions); - } - else - { - ifNotTest = ((PrimaryExpression) _test).ToValue(); - } + var testInstructions = _test.ToInstructions(start, "_t"); + ifNotTest = new Name(testInstructions.OfType().Last().Left); + instructions.AddRange(testInstructions); + } + else + { + ifNotTest = ((PrimaryExpression) _test).ToValue(); + } - var cOffset = start + instructions.Count + 1; - var consequentInstructions = _consequent.ToInstructions(cOffset, temp); + var cOffset = start + instructions.Count + 1; + var consequentInstructions = _consequent.ToInstructions(cOffset, temp); - var aOffset = consequentInstructions.Last().Number + 2; - var alternateInstructions = _alternate.ToInstructions(aOffset, temp); + var aOffset = consequentInstructions.Last().Number + 2; + var alternateInstructions = _alternate.ToInstructions(aOffset, temp); - instructions.Add( - new IfNotGoto( - ifNotTest, alternateInstructions.First().Number, cOffset - 1 - ) - ); - instructions.AddRange(consequentInstructions); - instructions.OfType().Last().Left = temp; + instructions.Add( + new IfNotGoto( + ifNotTest, alternateInstructions.First().Number, cOffset - 1 + ) + ); + instructions.AddRange(consequentInstructions); + instructions.OfType().Last().Left = temp; - instructions.Add( - new Goto(alternateInstructions.Last().Number + 1, aOffset - 1) - ); - instructions.AddRange(alternateInstructions); + instructions.Add( + new Goto(alternateInstructions.Last().Number + 1, aOffset - 1) + ); + instructions.AddRange(alternateInstructions); - return instructions; - } + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs index a2e6b8a8..a4a678a8 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/Expression.cs @@ -1,18 +1,15 @@ -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.IR.Ast.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public abstract class Expression : AbstractSyntaxTreeNode { - public abstract class Expression : AbstractSyntaxTreeNode + protected Expression() { - protected Expression() - { - CanEvaluate = true; - } + CanEvaluate = true; + } - public bool Primary() => !this.Any(); + public bool Primary() => !this.Any(); - public abstract List ToInstructions(int start, string temp); - } + public abstract List ToInstructions(int start, string temp); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs index 7f1eac93..596f8302 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/MemberExpression.cs @@ -1,73 +1,70 @@ -using System.Collections.Generic; 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.IR.Ast.Nodes.Expressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class MemberExpression : Expression { - public class MemberExpression : Expression - { - private readonly IdentifierReference _id; + private readonly IdentifierReference _id; - public AccessExpression AccessChain { get; } + public AccessExpression AccessChain { get; } - public MemberExpression(IdentifierReference id, AccessExpression accessChain) - { - _id = id; - _id.Parent = this; + public MemberExpression(IdentifierReference id, AccessExpression accessChain) + { + _id = id; + _id.Parent = this; - AccessChain = accessChain; - if (accessChain != null) - { - AccessChain.Parent = this; - } + AccessChain = accessChain; + if (accessChain != null) + { + AccessChain.Parent = this; } + } - public string Id => _id.Id; + public string Id => _id.Id; - internal override Type NodeCheck() + internal override Type NodeCheck() + { + if (AccessChain == null) { - if (AccessChain == null) - { - return _id.NodeCheck(); - } - - var symbol = SymbolTable.FindSymbol(_id.Id); - if (symbol == null) - { - throw new UnknownIdentifierReference(_id); - } - - return AccessChain.Check(symbol.Type); + return _id.NodeCheck(); } - public override IEnumerator GetEnumerator() + var symbol = SymbolTable.FindSymbol(_id.Id); + if (symbol == null) { - if (AccessChain != null) - { - yield return AccessChain; - } + throw new UnknownIdentifierReference(_id); } - protected override string NodeRepresentation() => Id; + return AccessChain.Check(symbol.Type); + } - public override List ToInstructions(int start, string temp) + public override IEnumerator GetEnumerator() + { + if (AccessChain != null) { - if (AccessChain != null && AccessChain.HasNext()) - { - return AccessChain.ToInstructions(start, _id.Id); - } + yield return AccessChain; + } + } - return new(); + protected override string NodeRepresentation() => Id; + + public override List ToInstructions(int start, string temp) + { + if (AccessChain != null && AccessChain.HasNext()) + { + return AccessChain.ToInstructions(start, _id.Id); } - public static implicit operator IdentifierReference(MemberExpression member) => - member._id; - - public static explicit operator MemberExpression(IdentifierReference idRef) => - new (idRef, null); + return new(); } + + public static implicit operator IdentifierReference(MemberExpression member) => + member._id; + + public static explicit operator MemberExpression(IdentifierReference idRef) => + new (idRef, null); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs index 74cd8ed8..7fd61bf9 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/IdentifierReference.cs @@ -2,37 +2,35 @@ 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.IR.Ast.Nodes.Expressions.PrimaryExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +public class IdentifierReference : PrimaryExpression { - public class IdentifierReference : PrimaryExpression - { - public string Id { get; } + public string Id { get; } - public IdentifierReference(string id) - { - Id = id; - } + public IdentifierReference(string id) + { + Id = id; + } - internal override Type NodeCheck() + internal override Type NodeCheck() + { + if (!ChildOf()) { - if (!ChildOf()) + var symbol = SymbolTable.FindSymbol(Id); + return symbol switch { - var symbol = SymbolTable.FindSymbol(Id); - return symbol switch - { - VariableSymbol v => v.Type, - FunctionSymbol f => f.Type, - _ => throw new UnknownIdentifierReference(this) - }; - } - - return null; + VariableSymbol v => v.Type, + FunctionSymbol f => f.Type, + _ => throw new UnknownIdentifierReference(this) + }; } - protected override string NodeRepresentation() => Id; - - public override IValue ToValue() => new Name(Id); + return null; } + + protected override string NodeRepresentation() => Id; + + public override IValue ToValue() => new Name(Id); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs index 7eacc3bd..b0286598 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/Literal.cs @@ -1,27 +1,25 @@ using Interpreter.Lib.BackEnd.Values; using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +public class Literal : PrimaryExpression { - public class Literal : PrimaryExpression - { - private readonly Type _type; - private readonly object _value; - private readonly string _label; + private readonly Type _type; + private readonly object _value; + private readonly string _label; - public Literal(Type type, object value, Segment segment = null, string label = null) - { - _type = type; - _label = label ?? value.ToString(); - _value = value; - Segment = segment; - } + public Literal(Type type, object value, Segment segment = null, string label = null) + { + _type = type; + _label = label ?? value.ToString(); + _value = value; + Segment = segment; + } - internal override Type NodeCheck() => _type; + internal override Type NodeCheck() => _type; - protected override string NodeRepresentation() => _label; + protected override string NodeRepresentation() => _label; - public override IValue ToValue() => new Constant(_value, _label); - } + public override IValue ToValue() => new Constant(_value, _label); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs index 59531d7e..15b785a4 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/PrimaryExpressions/PrimaryExpression.cs @@ -1,22 +1,20 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.BackEnd.Values; -namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; + +public abstract class PrimaryExpression : Expression { - public abstract class PrimaryExpression : Expression + public override IEnumerator GetEnumerator() { - public override IEnumerator GetEnumerator() - { - yield break; - } + yield break; + } - public abstract IValue ToValue(); + public abstract IValue ToValue(); - public override List ToInstructions(int start, string temp) => - new() - { - new Simple(temp, (null, ToValue()), "", start) - }; - } + public override List ToInstructions(int start, string temp) => + new() + { + new Simple(temp, (null, ToValue()), "", start) + }; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs b/Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs index f5530864..4b2a4a1e 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Expressions/UnaryExpression.cs @@ -1,94 +1,89 @@ -using System; -using System.Collections.Generic; -using System.Linq; 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 +namespace Interpreter.Lib.IR.Ast.Nodes.Expressions; + +public class UnaryExpression : Expression { - public class UnaryExpression : Expression + private readonly string _operator; + + private readonly Expression _expression; + + public UnaryExpression(string @operator, Expression expression) { - private readonly string _operator; + _operator = @operator; - private readonly Expression _expression; + _expression = expression; + _expression.Parent = this; + } - public UnaryExpression(string @operator, Expression expression) + internal override Type NodeCheck() + { + var eType = _expression.NodeCheck(); + Type retType; + if (eType.Equals(TypeUtils.JavaScriptTypes.Number) && _operator == "-") { - _operator = @operator; - - _expression = expression; - _expression.Parent = this; + retType = TypeUtils.JavaScriptTypes.Number; } - - internal override Type NodeCheck() + else if (eType.Equals(TypeUtils.JavaScriptTypes.Boolean) && _operator == "!") { - var eType = _expression.NodeCheck(); - Type retType; - if (eType.Equals(TypeUtils.JavaScriptTypes.Number) && _operator == "-") - { - retType = TypeUtils.JavaScriptTypes.Number; - } - else if (eType.Equals(TypeUtils.JavaScriptTypes.Boolean) && _operator == "!") - { - retType = TypeUtils.JavaScriptTypes.Boolean; - } - else if (eType is ArrayType && _operator == "~") - { - retType = TypeUtils.JavaScriptTypes.Number; - } - else throw new UnsupportedOperation(Segment, eType, _operator); - - return retType; + retType = TypeUtils.JavaScriptTypes.Boolean; } - - public override IEnumerator GetEnumerator() + else if (eType is ArrayType && _operator == "~") { - yield return _expression; + retType = TypeUtils.JavaScriptTypes.Number; } + else throw new UnsupportedOperation(Segment, eType, _operator); - protected override string NodeRepresentation() => _operator; + return retType; + } - public override List ToInstructions(int start, string temp) - { - var instructions = new List(); + public override IEnumerator GetEnumerator() + { + yield return _expression; + } - (IValue left, IValue right) right = (null, null); - if (_expression.Primary()) - { - right.right = ((PrimaryExpression) _expression).ToValue(); - } - else + protected override string NodeRepresentation() => _operator; + + public override List ToInstructions(int start, string temp) + { + var instructions = new List(); + + (IValue left, IValue right) right = (null, null); + if (_expression.Primary()) + { + right.right = ((PrimaryExpression) _expression).ToValue(); + } + else + { + instructions.AddRange(_expression.ToInstructions(start, temp)); + if (_expression is MemberExpression member && member.Any()) { - instructions.AddRange(_expression.ToInstructions(start, temp)); - if (_expression is MemberExpression member && member.Any()) + var i = start + instructions.Count; + var dest = "_t" + i; + var src = instructions.Any() + ? instructions.OfType().Last().Left + : member.Id; + var instruction = member.AccessChain.Tail switch { - var i = start + instructions.Count; - var dest = "_t" + i; - var src = instructions.Any() - ? instructions.OfType().Last().Left - : member.Id; - var instruction = member.AccessChain.Tail switch - { - DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", i), - IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", i), - _ => throw new NotImplementedException() - }; - instructions.Add(instruction); - } - right.right = new Name(instructions.OfType().Last().Left); + DotAccess dot => new Simple(dest, (new Name(src), new Constant(dot.Id, dot.Id)), ".", i), + IndexAccess index => new Simple(dest, (new Name(src), index.Expression.ToValue()), "[]", i), + _ => throw new NotImplementedException() + }; + instructions.Add(instruction); } + right.right = new Name(instructions.OfType().Last().Left); + } - var number = instructions.Any() ? instructions.Last().Number + 1 : start; + var number = instructions.Any() ? instructions.Last().Number + 1 : start; - instructions.Add(new Simple( - temp + number, right, _operator, number - )); - return instructions; - } + instructions.Add(new Simple( + temp + number, right, _operator, number + )); + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs b/Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs index 862b871c..c75066d8 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/ScriptBody.cs @@ -1,25 +1,23 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.IR.Ast.Visitors; -namespace Interpreter.Lib.IR.Ast.Nodes +namespace Interpreter.Lib.IR.Ast.Nodes; + +public class ScriptBody : AbstractSyntaxTreeNode { - public class ScriptBody : AbstractSyntaxTreeNode - { - public List StatementList { get; } + public List StatementList { get; } - public ScriptBody(IEnumerable statementList) - { - StatementList = new List(statementList); - StatementList.ForEach(item => item.Parent = this); - } + public ScriptBody(IEnumerable statementList) + { + StatementList = new List(statementList); + StatementList.ForEach(item => item.Parent = this); + } - public override IEnumerator GetEnumerator() => - StatementList.GetEnumerator(); + public override IEnumerator GetEnumerator() => + StatementList.GetEnumerator(); - protected override string NodeRepresentation() => "Script"; + protected override string NodeRepresentation() => "Script"; - public override List Accept(InstructionProvider visitor) => - visitor.Visit(this); - } + public override List Accept(InstructionProvider visitor) => + visitor.Visit(this); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs b/Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs index 27c0b80d..7a9ebda7 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/StatementListItem.cs @@ -1,7 +1,6 @@ -namespace Interpreter.Lib.IR.Ast.Nodes +namespace Interpreter.Lib.IR.Ast.Nodes; + +public abstract class StatementListItem : AbstractSyntaxTreeNode { - public abstract class StatementListItem : AbstractSyntaxTreeNode - { - public abstract bool IsStatement(); - } + public abstract bool IsStatement(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs index 59f55af7..004e0ed3 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/BlockStatement.cs @@ -1,54 +1,51 @@ -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class BlockStatement : Statement { - public class BlockStatement : Statement + private readonly List _statementList; + + public BlockStatement(IEnumerable statementList) { - private readonly List _statementList; + _statementList = new List(statementList); + _statementList.ForEach(item => item.Parent = this); + } - public BlockStatement(IEnumerable statementList) + public bool HasReturnStatement() + { + var has = _statementList.Any(item => item is ReturnStatement); + if (!has) { - _statementList = new List(statementList); - _statementList.ForEach(item => item.Parent = this); + has = _statementList + .Where(item => item.IsStatement()) + .OfType() + .Any(ifStmt => ifStmt.HasReturnStatement()); } - public bool HasReturnStatement() - { - var has = _statementList.Any(item => item is ReturnStatement); - if (!has) - { - has = _statementList - .Where(item => item.IsStatement()) - .OfType() - .Any(ifStmt => ifStmt.HasReturnStatement()); - } - - return has; - } + return has; + } - public override IEnumerator GetEnumerator() => _statementList.GetEnumerator(); + public override IEnumerator GetEnumerator() => _statementList.GetEnumerator(); - protected override string NodeRepresentation() => "{}"; + protected override string NodeRepresentation() => "{}"; - public override List ToInstructions(int start) + public override List ToInstructions(int start) + { + var blockInstructions = new List(); + var offset = start; + foreach (var item in _statementList) { - var blockInstructions = new List(); - var offset = start; - foreach (var item in _statementList) + var itemInstructions = item.ToInstructions(offset); + blockInstructions.AddRange(itemInstructions); + if (item is ReturnStatement) { - var itemInstructions = item.ToInstructions(offset); - blockInstructions.AddRange(itemInstructions); - if (item is ReturnStatement) - { - break; - } - - offset += itemInstructions.Count; + break; } - return blockInstructions; + offset += itemInstructions.Count; } + + return blockInstructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs index 25431d32..c1cfb42b 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/BreakStatement.cs @@ -1,16 +1,14 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class BreakStatement : InsideLoopStatement { - public class BreakStatement : InsideLoopStatement - { - protected override string NodeRepresentation() => "break"; + protected override string NodeRepresentation() => "break"; - public override List ToInstructions(int start) => - new() - { - new Goto(-1, start) - }; - } + public override List ToInstructions(int start) => + new() + { + new Goto(-1, start) + }; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs index 3fe7b118..d4374d10 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/ContinueStatement.cs @@ -1,16 +1,14 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class ContinueStatement : InsideLoopStatement { - public class ContinueStatement : InsideLoopStatement - { - protected override string NodeRepresentation() => "continue"; + protected override string NodeRepresentation() => "continue"; - public override List ToInstructions(int start) => - new() - { - new Goto(-2, start) - }; - } + public override List ToInstructions(int start) => + new() + { + new Goto(-2, start) + }; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs index be9d9a04..7893e7af 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/ExpressionStatement.cs @@ -1,26 +1,23 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; -using Interpreter.Lib.IR.Ast.Nodes.Expressions; -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class ExpressionStatement : Statement { - public class ExpressionStatement : Statement - { - private readonly Expression _expression; + private readonly Expression _expression; - public ExpressionStatement(Expression expression) - { - _expression = expression; - expression.Parent = this; - } + public ExpressionStatement(Expression expression) + { + _expression = expression; + expression.Parent = this; + } - public override IEnumerator GetEnumerator() - { - yield return _expression; - } + public override IEnumerator GetEnumerator() + { + yield return _expression; + } - protected override string NodeRepresentation() => nameof(ExpressionStatement); + protected override string NodeRepresentation() => nameof(ExpressionStatement); - public override List ToInstructions(int start) => _expression.ToInstructions(start); - } + public override List ToInstructions(int start) => _expression.ToInstructions(start); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs index d2d4694f..6063078b 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/IfStatement.cs @@ -1,129 +1,125 @@ -using System.Collections.Generic; -using System.Linq; 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 +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class IfStatement : Statement { - public class IfStatement : Statement + private readonly Expression _test; + private readonly Statement _then; + private readonly Statement _else; + + public IfStatement(Expression test, Statement then, Statement @else = null) { - private readonly Expression _test; - private readonly Statement _then; - private readonly Statement _else; + _test = test; + _test.Parent = this; - public IfStatement(Expression test, Statement then, Statement @else = null) + _then = then; + _then.Parent = this; + + if (@else != null) { - _test = test; - _test.Parent = this; + _else = @else; + _else.Parent = this; + } - _then = then; - _then.Parent = this; + CanEvaluate = true; + } - if (@else != null) + public bool HasReturnStatement() + { + var thenResult = _then is ReturnStatement; + if (!thenResult) + { + if (_then is BlockStatement block) { - _else = @else; - _else.Parent = this; + thenResult = block.HasReturnStatement(); } - - CanEvaluate = true; } - public bool HasReturnStatement() + var elseResult = _else == null || _else is ReturnStatement; + if (!elseResult) { - var thenResult = _then is ReturnStatement; - if (!thenResult) + if (_else is BlockStatement block) { - if (_then is BlockStatement block) - { - thenResult = block.HasReturnStatement(); - } + elseResult = block.HasReturnStatement(); } + } - var elseResult = _else == null || _else is ReturnStatement; - if (!elseResult) - { - if (_else is BlockStatement block) - { - elseResult = block.HasReturnStatement(); - } - } + return thenResult && elseResult; + } - return thenResult && elseResult; + public override IEnumerator GetEnumerator() + { + yield return _test; + yield return _then; + if (_else != null) + { + yield return _else; } + } - public override IEnumerator GetEnumerator() + internal override Type NodeCheck() + { + var testType = _test.NodeCheck(); + if (!testType.Equals(TypeUtils.JavaScriptTypes.Boolean)) { - yield return _test; - yield return _then; - if (_else != null) - { - yield return _else; - } + throw new NotBooleanTestExpression(Segment, testType); } - internal override Type NodeCheck() + return testType; + } + + protected override string NodeRepresentation() => "if"; + + public override List ToInstructions(int start) + { + var instructions = new List(); + if (_then.Any() && (_else == null || _else.Any())) { - var testType = _test.NodeCheck(); - if (!testType.Equals(TypeUtils.JavaScriptTypes.Boolean)) + IValue ifNotTest; + if (!_test.Primary()) + { + var testInstructions = _test.ToInstructions(start, "_t"); + ifNotTest = new Name(testInstructions.OfType().Last().Left); + instructions.AddRange(testInstructions); + } + else { - throw new NotBooleanTestExpression(Segment, testType); + ifNotTest = ((PrimaryExpression) _test).ToValue(); } - return testType; - } + var tOffset = start + instructions.Count + 1; + var thenInstructions = _then.ToInstructions(tOffset); - protected override string NodeRepresentation() => "if"; + var eOffset = thenInstructions.Any() + ? thenInstructions.Last().Number + 2 + : tOffset + 1; + var elseInstructions = _else?.ToInstructions(eOffset); - public override List ToInstructions(int start) - { - var instructions = new List(); - if (_then.Any() && (_else == null || _else.Any())) - { - IValue ifNotTest; - if (!_test.Primary()) - { - var testInstructions = _test.ToInstructions(start, "_t"); - ifNotTest = new Name(testInstructions.OfType().Last().Left); - instructions.AddRange(testInstructions); - } - else - { - ifNotTest = ((PrimaryExpression) _test).ToValue(); - } - - var tOffset = start + instructions.Count + 1; - var thenInstructions = _then.ToInstructions(tOffset); - - var eOffset = thenInstructions.Any() - ? thenInstructions.Last().Number + 2 - : tOffset + 1; - var elseInstructions = _else?.ToInstructions(eOffset); + instructions.Add( + new IfNotGoto( + ifNotTest, elseInstructions?.First().Number ?? eOffset - 1, tOffset - 1 + ) + ); + + instructions.AddRange(thenInstructions); + if (elseInstructions != null) + { instructions.Add( - new IfNotGoto( - ifNotTest, elseInstructions?.First().Number ?? eOffset - 1, tOffset - 1 + new Goto( + elseInstructions.Last().Number + 1, + eOffset - 1 ) ); - - instructions.AddRange(thenInstructions); - - if (elseInstructions != null) - { - instructions.Add( - new Goto( - elseInstructions.Last().Number + 1, - eOffset - 1 - ) - ); - instructions.AddRange(elseInstructions); - } + instructions.AddRange(elseInstructions); } - - return instructions; } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs index 131ac296..77744c3a 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/InsideLoopStatement.cs @@ -1,28 +1,25 @@ -using System.Collections.Generic; using Interpreter.Lib.IR.CheckSemantics.Exceptions; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public abstract class InsideLoopStatement : Statement { - public abstract class InsideLoopStatement : Statement + protected InsideLoopStatement() { - protected InsideLoopStatement() - { - CanEvaluate = true; - } + CanEvaluate = true; + } - internal override Type NodeCheck() + internal override Type NodeCheck() + { + if (!ChildOf()) { - if (!ChildOf()) - { - throw new OutsideOfLoop(Segment, NodeRepresentation()); - } - return null; + throw new OutsideOfLoop(Segment, NodeRepresentation()); } + return null; + } - public override IEnumerator GetEnumerator() - { - yield break; - } + public override IEnumerator GetEnumerator() + { + yield break; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs index c2f5dae7..dced5513 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/ReturnStatement.cs @@ -1,95 +1,91 @@ -using System.Collections.Generic; -using System.Linq; 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.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class ReturnStatement : Statement { - public class ReturnStatement : Statement - { - private readonly Expression _expression; + private readonly Expression _expression; - public ReturnStatement(Expression expression = null) + public ReturnStatement(Expression expression = null) + { + _expression = expression; + CanEvaluate = true; + if (expression != null) { - _expression = expression; - CanEvaluate = true; - if (expression != null) - { - _expression.Parent = this; - } + _expression.Parent = this; } + } - internal override Type NodeCheck() + internal override Type NodeCheck() + { + if (!ChildOf()) { - if (!ChildOf()) - { - throw new ReturnOutsideFunction(Segment); - } - - return _expression?.NodeCheck() ?? TypeUtils.JavaScriptTypes.Void; + throw new ReturnOutsideFunction(Segment); } - public override IEnumerator GetEnumerator() - { - if (_expression == null) - { - yield break; - } + return _expression?.NodeCheck() ?? TypeUtils.JavaScriptTypes.Void; + } - yield return _expression; + public override IEnumerator GetEnumerator() + { + if (_expression == null) + { + yield break; } - protected override string NodeRepresentation() => "return"; + yield return _expression; + } + + protected override string NodeRepresentation() => "return"; - private FunctionSymbol GetCallee() + private FunctionSymbol GetCallee() + { + var parent = Parent; + while (parent != null) { - var parent = Parent; - while (parent != null) + if (parent is FunctionDeclaration declaration) { - if (parent is FunctionDeclaration declaration) - { - return declaration.GetSymbol(); - } - - parent = parent.Parent; + return declaration.GetSymbol(); } - return null; + parent = parent.Parent; } - public override List ToInstructions(int start) + return null; + } + + public override List ToInstructions(int start) + { + var instructions = new List(); + if (_expression == null) + { + instructions.Add(new Return(GetCallee().CallInfo.Location, start)); + } + else { - var instructions = new List(); - if (_expression == null) + if (_expression.Primary()) { - instructions.Add(new Return(GetCallee().CallInfo.Location, start)); + instructions.Add(new Return( + GetCallee().CallInfo.Location, start, ((PrimaryExpression) _expression).ToValue()) + ); } else { - if (_expression.Primary()) - { - instructions.Add(new Return( - GetCallee().CallInfo.Location, start, ((PrimaryExpression) _expression).ToValue()) - ); - } - else - { - var eInstructions = _expression.ToInstructions(start, "_t"); - var last = eInstructions.OfType().Last(); - instructions.AddRange(eInstructions); - instructions.Add(new Return( - GetCallee().CallInfo.Location, last.Number + 1, new Name(last.Left) - )); - } + var eInstructions = _expression.ToInstructions(start, "_t"); + var last = eInstructions.OfType().Last(); + instructions.AddRange(eInstructions); + instructions.Add(new Return( + GetCallee().CallInfo.Location, last.Number + 1, new Name(last.Left) + )); } - - return instructions; } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs index 79f1bdd6..2a4f7f0d 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/Statement.cs @@ -1,7 +1,6 @@ -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public abstract class Statement : StatementListItem { - public abstract class Statement : StatementListItem - { - public override bool IsStatement() => true; - } + public override bool IsStatement() => true; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs index 937eee38..07563b27 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/TypeStatement.cs @@ -1,25 +1,21 @@ -using System.Collections.Generic; -using Interpreter.Lib.IR.CheckSemantics.Types; +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; -namespace Interpreter.Lib.IR.Ast.Nodes.Statements +public class TypeStatement : Statement { - public class TypeStatement : Statement - { - private readonly string _typeId; - private readonly Type _typeValue; + private readonly string _typeId; + private readonly Type _typeValue; - public TypeStatement(string typeId, Type typeValue) - { - _typeId = typeId; - _typeValue = typeValue; - } + public TypeStatement(string typeId, Type typeValue) + { + _typeId = typeId; + _typeValue = typeValue; + } - public override IEnumerator GetEnumerator() - { - yield break; - } - - protected override string NodeRepresentation() => - $"type {_typeId} = {_typeValue}"; + public override IEnumerator GetEnumerator() + { + yield break; } + + protected override string NodeRepresentation() => + $"type {_typeId} = {_typeValue}"; } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs b/Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs index af2e4e7b..ac6c987e 100644 --- a/Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs +++ b/Interpreter.Lib/IR/Ast/Nodes/Statements/WhileStatement.cs @@ -1,94 +1,90 @@ -using System.Collections.Generic; -using System.Linq; 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 +namespace Interpreter.Lib.IR.Ast.Nodes.Statements; + +public class WhileStatement : Statement { - public class WhileStatement : Statement + private readonly Expression _condition; + private readonly Statement _statement; + + public WhileStatement(Expression condition, Statement statement) { - private readonly Expression _condition; - private readonly Statement _statement; + _condition = condition; + _condition.Parent = this; - public WhileStatement(Expression condition, Statement statement) - { - _condition = condition; - _condition.Parent = this; + _statement = statement; + _statement.Parent = this; - _statement = statement; - _statement.Parent = this; + CanEvaluate = true; + } - CanEvaluate = true; - } + public override IEnumerator GetEnumerator() + { + yield return _condition; + yield return _statement; + } - public override IEnumerator GetEnumerator() + internal override Type NodeCheck() + { + var condType = _condition.NodeCheck(); + if (!condType.Equals(TypeUtils.JavaScriptTypes.Boolean)) { - yield return _condition; - yield return _statement; + throw new NotBooleanTestExpression(Segment, condType); } - internal override Type NodeCheck() - { - var condType = _condition.NodeCheck(); - if (!condType.Equals(TypeUtils.JavaScriptTypes.Boolean)) - { - throw new NotBooleanTestExpression(Segment, condType); - } - - return condType; - } + return condType; + } - protected override string NodeRepresentation() => "while"; + protected override string NodeRepresentation() => "while"; - public override List ToInstructions(int start) + public override List ToInstructions(int start) + { + var instructions = new List(); + IValue ifNotTest; + if (!_condition.Primary()) + { + var conditionInstructions = _condition.ToInstructions(start, "_t"); + ifNotTest = new Name(conditionInstructions.OfType().Last().Left); + instructions.AddRange(conditionInstructions); + } + else { - var instructions = new List(); - IValue ifNotTest; - if (!_condition.Primary()) - { - var conditionInstructions = _condition.ToInstructions(start, "_t"); - ifNotTest = new Name(conditionInstructions.OfType().Last().Left); - instructions.AddRange(conditionInstructions); - } - else - { - ifNotTest = ((PrimaryExpression) _condition).ToValue(); - } + ifNotTest = ((PrimaryExpression) _condition).ToValue(); + } - var cOffset = start + instructions.Count + 1; - var loopBody = _statement.ToInstructions(cOffset); - if (loopBody.Any()) - { - instructions.Add(new IfNotGoto(ifNotTest, loopBody.Last().Number + 2, cOffset - 1)); - instructions.AddRange(loopBody); - instructions.Add(new Goto(start, loopBody.Last().Number + 1)); + var cOffset = start + instructions.Count + 1; + var loopBody = _statement.ToInstructions(cOffset); + if (loopBody.Any()) + { + instructions.Add(new IfNotGoto(ifNotTest, loopBody.Last().Number + 2, cOffset - 1)); + instructions.AddRange(loopBody); + instructions.Add(new Goto(start, loopBody.Last().Number + 1)); - loopBody - .OfType() - .Where(g => g.Jump() < 0) - .ToList() - .ForEach(j => + loopBody + .OfType() + .Where(g => g.Jump() < 0) + .ToList() + .ForEach(j => + { + if (j.Jump() == -1) { - if (j.Jump() == -1) - { - j.SetJump(loopBody.Last().Number + 2); - } - else if (j.Jump() == -2) - { - j.SetJump(start); - } - }); - } - else - { - instructions.Clear(); - } - - return instructions; + j.SetJump(loopBody.Last().Number + 2); + } + else if (j.Jump() == -2) + { + j.SetJump(start); + } + }); } + else + { + instructions.Clear(); + } + + return instructions; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Visitors/InstructionProvider.cs b/Interpreter.Lib/IR/Ast/Visitors/InstructionProvider.cs index 9fdc5427..9dadd920 100644 --- a/Interpreter.Lib/IR/Ast/Visitors/InstructionProvider.cs +++ b/Interpreter.Lib/IR/Ast/Visitors/InstructionProvider.cs @@ -1,35 +1,33 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.IR.Ast.Nodes; using Interpreter.Lib.IR.Ast.Nodes.Declarations; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.Ast.Visitors +namespace Interpreter.Lib.IR.Ast.Visitors; + +public class InstructionProvider : + IVisitor>, + IVisitor> { - public class InstructionProvider : - IVisitor>, - IVisitor> + public List Visit(ScriptBody visitable) { - public List Visit(ScriptBody visitable) + var result = new List(); + foreach (var listItem in visitable.StatementList) { - var result = new List(); - foreach (var listItem in visitable.StatementList) - { - result.AddRange(listItem.Accept(this)); - } - - return result; + result.AddRange(listItem.Accept(this)); } - public List Visit(LexicalDeclaration visitable) - { - var result = new List(); - foreach (var assignment in visitable.Assignments) - { - result.AddRange(assignment.Accept(this)); - } + return result; + } - return result; + public List Visit(LexicalDeclaration visitable) + { + var result = new List(); + foreach (var assignment in visitable.Assignments) + { + result.AddRange(assignment.Accept(this)); } + + return result; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/Ast/Visitors/SemanticChecker.cs b/Interpreter.Lib/IR/Ast/Visitors/SemanticChecker.cs index da9a8c18..3eae1d69 100644 --- a/Interpreter.Lib/IR/Ast/Visitors/SemanticChecker.cs +++ b/Interpreter.Lib/IR/Ast/Visitors/SemanticChecker.cs @@ -1,8 +1,7 @@ using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.Ast.Visitors +namespace Interpreter.Lib.IR.Ast.Visitors; + +public class SemanticChecker : IVisitor { - public class SemanticChecker : IVisitor - { - } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs index d3e08b3e..bd176e61 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ArrayAccessException.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class ArrayAccessException : SemanticException { - 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") { } - } + 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 index 6735bea0..353b87ea 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/AssignmentToConst.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class AssignmentToConst : SemanticException { - public class AssignmentToConst : SemanticException - { - public AssignmentToConst(IdentifierReference ident) : - base(ident.Segment,$"Cannot assign to const: {ident.Id}") { } - } + 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 index 0881f2dd..2a2dd640 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/CannotDefineType.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class CannotDefineType : SemanticException { - public class CannotDefineType : SemanticException - { - public CannotDefineType(Segment segment) : - base(segment, "Cannot define type") { } - } + 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 index b86ec5ef..9d451dd1 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ConstWithoutInitializer.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class ConstWithoutInitializer : SemanticException { - public class ConstWithoutInitializer : SemanticException - { - public ConstWithoutInitializer(IdentifierReference ident) : - base(ident.Segment, $"Const without initializer: {ident.Id}") { } - } + 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 index 8819da8e..ddb751f9 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/DeclarationAlreadyExists.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class DeclarationAlreadyExists : SemanticException { - public class DeclarationAlreadyExists : SemanticException - { - public DeclarationAlreadyExists(IdentifierReference ident) : - base(ident.Segment, $"Declaration already exists: {ident.Id}") { } - } + 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 index 7d1ffd9b..09098d33 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/FunctionWithoutReturnStatement.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class FunctionWithoutReturnStatement : SemanticException { - public class FunctionWithoutReturnStatement : SemanticException - { - public FunctionWithoutReturnStatement(Segment segment) : - base(segment, "function with non-void return type must have a return statement") { } - } + 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 index 248be0fc..d896c792 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/IncompatibleTypesOfOperands.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class IncompatibleTypesOfOperands : SemanticException { - public class IncompatibleTypesOfOperands : SemanticException - { - public IncompatibleTypesOfOperands(Segment segment, Type left, Type right) : - base(segment, $"Incompatible types of operands: {left} and {right}") { } - } + 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 index 84d8e6f2..a1940bb2 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/NotBooleanTestExpression.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class NotBooleanTestExpression : SemanticException { - public class NotBooleanTestExpression : SemanticException - { - public NotBooleanTestExpression(Segment segment, Type type) : - base(segment, $"Type of expression is {type} but expected boolean") { } - } + 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 index 65c74162..ae459389 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ObjectAccessException.cs @@ -1,11 +1,10 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class ObjectAccessException : SemanticException { - public class ObjectAccessException : SemanticException - { - public ObjectAccessException(Segment segment, ObjectType objectType, string field) : - base(segment, $"Object type {objectType} has no field {field}") { } - } + 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 index 3db001af..2049c6cf 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/OutsideOfLoop.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/OutsideOfLoop.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class OutsideOfLoop : SemanticException { - public class OutsideOfLoop : SemanticException - { - public OutsideOfLoop(Segment segment, string keyword) : - base(segment, $"\"{keyword}\" outside of loop") { } - } + 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 index 20d67a72..bd27215e 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/ReturnOutsideFunction.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class ReturnOutsideFunction : SemanticException { - public class ReturnOutsideFunction : SemanticException - { - public ReturnOutsideFunction(Segment segment) : - base(segment, "\"return\" outside function") { } - } + 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 index 36d9b978..1571a424 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/SemanticException.cs @@ -1,18 +1,16 @@ -using System; using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +[Serializable] +public abstract class SemanticException : Exception { - [Serializable] - public abstract class SemanticException : Exception - { - protected SemanticException() { } + protected SemanticException() { } - protected SemanticException(string message) : base(message) { } + protected SemanticException(string message) : base(message) { } - protected SemanticException(string message, Exception inner) : base(message, inner) { } + protected SemanticException(string message, Exception inner) : base(message, inner) { } - protected SemanticException(Segment segment, string message) : - base($"{segment} {message}") { } - } + 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 index 2fae5f0d..5f3609e5 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/SymbolIsNotCallable.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class SymbolIsNotCallable: SemanticException { - public class SymbolIsNotCallable: SemanticException - { - public SymbolIsNotCallable(string symbol, Segment segment) : - base(segment, $"Symbol is not callable: {symbol}") { } - } + 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 index 4aa9862a..99397033 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnknownIdentifierReference.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.IR.Ast.Nodes.Expressions.PrimaryExpressions; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class UnknownIdentifierReference : SemanticException { - public class UnknownIdentifierReference : SemanticException - { - public UnknownIdentifierReference(IdentifierReference ident) : - base(ident.Segment, $"Unknown identifier reference: {ident.Id}") { } - } + 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 index a875e1f6..e6194f7f 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/UnsupportedOperation.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class UnsupportedOperation : SemanticException { - public class UnsupportedOperation : SemanticException - { - public UnsupportedOperation(Segment segment, Type type, string @operator) : - base(segment, $"Type {type} does not support operation {@operator}") { } - } + 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 index 4386f41e..63b09d55 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongArrayLiteralDeclaration.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class WrongArrayLiteralDeclaration : SemanticException { - 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}") { } - } + 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 index 6ea3a806..eb2aaa3e 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongConditionalTypes.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class WrongConditionalTypes : SemanticException { - 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}") { } - } + 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 index 490991a9..630cc175 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongNumberOfArguments.cs @@ -1,10 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class WrongNumberOfArguments : SemanticException { - public class WrongNumberOfArguments : SemanticException - { - public WrongNumberOfArguments(Segment segment, int expected, int actual) : - base(segment, $"Wrong number of arguments: expected {expected}, actual {actual}") { } - } + 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 index 617516b5..203ad081 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongReturnType.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class WrongReturnType : SemanticException { - public class WrongReturnType : SemanticException - { - public WrongReturnType(Segment segment, Type expected, Type actual) : - base(segment, $"Wrong return type: expected {expected}, actual {actual}") { } - } + 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 index da00ce69..6b34e8c2 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Exceptions/WrongTypeOfArgument.cs @@ -1,11 +1,9 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Exceptions +namespace Interpreter.Lib.IR.CheckSemantics.Exceptions; + +public class WrongTypeOfArgument : SemanticException { - public class WrongTypeOfArgument : SemanticException - { - public WrongTypeOfArgument(Segment segment, Type expected, Type actual) : - base(segment,$"Wrong type of argument: expected {expected}, actual {actual}") { } - } + 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/IR/CheckSemantics/Types/Any.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Any.cs index cefb8955..ff982fbc 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/Any.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Any.cs @@ -1,13 +1,12 @@ -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class Any : Type { - public class Any : Type + public Any() : base("any") { - public Any() : base("any") - { - } + } - public override bool Equals(object obj) => true; + public override bool Equals(object obj) => true; - public override int GetHashCode() => "any".GetHashCode(); - } + public override int GetHashCode() => "any".GetHashCode(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs index f395ff34..5ba7fdee 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/ArrayType.cs @@ -1,36 +1,35 @@ using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class ArrayType : Type { - public class ArrayType : Type - { - public Type Type { get; set; } + public Type Type { get; set; } - public ArrayType(Type type) : base($"{type}[]") - { - Type = type; - } + public ArrayType(Type type) : base($"{type}[]") + { + Type = type; + } - public override Unit Accept(ReferenceResolver visitor) => - visitor.Visit(this); + public override Unit Accept(ReferenceResolver visitor) => + visitor.Visit(this); - public override string Accept(ObjectTypePrinter visitor) => - visitor.Visit(this); + public override string Accept(ObjectTypePrinter visitor) => + visitor.Visit(this); - public override int Accept(ObjectTypeHasher visitor) => - visitor.Visit(this); + public override int Accept(ObjectTypeHasher visitor) => + visitor.Visit(this); - public override bool Equals(object obj) - { - if (ReferenceEquals(this, obj)) return true; - if (obj == null || GetType() != obj.GetType()) return false; - var that = (ArrayType) obj; - return Equals(Type, that.Type); - } - - public override int GetHashCode() => - // ReSharper disable once NonReadonlyMemberInGetHashCode - Type.GetHashCode(); + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) return true; + if (obj == null || GetType() != obj.GetType()) return false; + var that = (ArrayType) obj; + return Equals(Type, that.Type); } + + public override int GetHashCode() => + // ReSharper disable once NonReadonlyMemberInGetHashCode + Type.GetHashCode(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs index 5045fee2..98f3296b 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/FunctionType.cs @@ -1,60 +1,56 @@ -using System; -using System.Collections.Generic; -using System.Linq; using System.Text; using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class FunctionType : Type { - public class FunctionType : Type - { - public Type ReturnType { get; set; } + public Type ReturnType { get; set; } - public List Arguments { get; } + public List Arguments { get; } - public FunctionType(Type returnType, IEnumerable arguments) - { - ReturnType = returnType; - Arguments = new List(arguments); - } + public FunctionType(Type returnType, IEnumerable arguments) + { + ReturnType = returnType; + Arguments = new List(arguments); + } - public override Unit Accept(ReferenceResolver visitor) => - visitor.Visit(this); + public override Unit Accept(ReferenceResolver visitor) => + visitor.Visit(this); - public override string Accept(ObjectTypePrinter visitor) => - visitor.Visit(this); + public override string Accept(ObjectTypePrinter visitor) => + visitor.Visit(this); - public override int Accept(ObjectTypeHasher visitor) => - visitor.Visit(this); + public override int Accept(ObjectTypeHasher visitor) => + visitor.Visit(this); - public override bool Equals(object obj) - { - if (ReferenceEquals(this, obj)) return true; - if (obj == null || GetType() != obj.GetType()) return false; - var that = (FunctionType) obj; - return ReturnType.Equals(that.ReturnType) && - Arguments.Count == that.Arguments.Count && - Arguments.Zip(that.Arguments) - .All(pair => pair.First.Equals(pair.Second)); - } + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) return true; + if (obj == null || GetType() != obj.GetType()) return false; + var that = (FunctionType) obj; + return ReturnType.Equals(that.ReturnType) && + Arguments.Count == that.Arguments.Count && + Arguments.Zip(that.Arguments) + .All(pair => pair.First.Equals(pair.Second)); + } - public override int GetHashCode() => - HashCode.Combine( - // ReSharper disable once NonReadonlyMemberInGetHashCode - ReturnType, - Arguments - .Select(arg => arg.GetHashCode()) - .Aggregate(36, HashCode.Combine) - ); + public override int GetHashCode() => + HashCode.Combine( + // ReSharper disable once NonReadonlyMemberInGetHashCode + ReturnType, + Arguments + .Select(arg => arg.GetHashCode()) + .Aggregate(36, HashCode.Combine) + ); - public override string ToString() => - new StringBuilder() - .Append('(') - .AppendJoin(", ", Arguments) - .Append(')') - .Append(" => ") - .Append(ReturnType) - .ToString(); - } + public override string ToString() => + new StringBuilder() + .Append('(') + .AppendJoin(", ", Arguments) + .Append(')') + .Append(" => ") + .Append(ReturnType) + .ToString(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs index c5712b55..8d78a520 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/NullType.cs @@ -1,17 +1,16 @@ -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class NullType : Type { - public class NullType : Type + public NullType() : base("null") { - public NullType() : base("null") - { - } - - public override bool Equals(object obj) - { - return obj is NullableType or NullType; - } + } - public override int GetHashCode() => - "null".GetHashCode(); + public override bool Equals(object obj) + { + return obj is NullableType or NullType; } + + public override int GetHashCode() => + "null".GetHashCode(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs index 77b8f2b5..489d0a4e 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/NullableType.cs @@ -1,41 +1,40 @@ using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class NullableType : Type { - public class NullableType : Type - { - public Type Type { get; set; } + public Type Type { get; set; } - public NullableType(Type type) : base($"{type}?") - { - Type = type; - } + public NullableType(Type type) : base($"{type}?") + { + Type = type; + } - protected NullableType() - { - } + protected NullableType() + { + } - public override Unit Accept(ReferenceResolver visitor) => - visitor.Visit(this); + public override Unit Accept(ReferenceResolver visitor) => + visitor.Visit(this); - public override string Accept(ObjectTypePrinter visitor) => - visitor.Visit(this); + public override string Accept(ObjectTypePrinter visitor) => + visitor.Visit(this); - public override int Accept(ObjectTypeHasher visitor) => - visitor.Visit(this); + public override int Accept(ObjectTypeHasher visitor) => + visitor.Visit(this); - public override bool Equals(object obj) + public override bool Equals(object obj) + { + if (obj is NullableType that) { - if (obj is NullableType that) - { - return Type.Equals(that.Type); - } - return obj is NullType; + return Type.Equals(that.Type); } - - public override int GetHashCode() => - // ReSharper disable once NonReadonlyMemberInGetHashCode - Type.GetHashCode(); + return obj is NullType; } + + public override int GetHashCode() => + // ReSharper disable once NonReadonlyMemberInGetHashCode + Type.GetHashCode(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs b/Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs index cf30671f..57f30446 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/ObjectType.cs @@ -1,73 +1,70 @@ -using System.Collections.Generic; -using System.Linq; using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class ObjectType : NullableType { - public class ObjectType : NullableType - { - private readonly Dictionary _properties; - private readonly ObjectTypeHasher _hasher; - private readonly ObjectTypePrinter _serializer; + private readonly Dictionary _properties; + private readonly ObjectTypeHasher _hasher; + private readonly ObjectTypePrinter _serializer; - public ObjectType(IEnumerable properties) - { - _properties = properties - .OrderBy(x => x.Id) - .ToDictionary( - x => x.Id, - x => x.Type - ); - _hasher = new ObjectTypeHasher(this); - _serializer = new ObjectTypePrinter(this); - } + public ObjectType(IEnumerable properties) + { + _properties = properties + .OrderBy(x => x.Id) + .ToDictionary( + x => x.Id, + x => x.Type + ); + _hasher = new ObjectTypeHasher(this); + _serializer = new ObjectTypePrinter(this); + } - public Type this[string id] - { - get => _properties.ContainsKey(id) - ? _properties[id] - : null; - set => _properties[id] = value; - } + public Type this[string id] + { + get => _properties.ContainsKey(id) + ? _properties[id] + : null; + set => _properties[id] = value; + } - public IEnumerable Keys => _properties.Keys; + public IEnumerable Keys => _properties.Keys; - public void ResolveSelfReferences(string self) => - new ReferenceResolver(this, self) - .Visit(this); + public void ResolveSelfReferences(string self) => + new ReferenceResolver(this, self) + .Visit(this); - public override Unit Accept(ReferenceResolver visitor) => - visitor.Visit(this); + public override Unit Accept(ReferenceResolver visitor) => + visitor.Visit(this); - public override string Accept(ObjectTypePrinter visitor) => - visitor.Visit(this); + public override string Accept(ObjectTypePrinter visitor) => + visitor.Visit(this); - public override int Accept(ObjectTypeHasher visitor) => - visitor.Visit(this); + public override int Accept(ObjectTypeHasher visitor) => + visitor.Visit(this); - public override bool Equals(object obj) + public override bool Equals(object obj) + { + if (obj is ObjectType that) { - if (obj is ObjectType that) - { - return ReferenceEquals(this, that) || _properties.Count == that._properties.Count && - _properties - .Zip(that._properties) - .All(pair => - pair.First.Key == pair.Second.Key && - pair.First.Value.Equals(pair.Second.Value) - ); - } - - return obj is NullType; + return ReferenceEquals(this, that) || _properties.Count == that._properties.Count && + _properties + .Zip(that._properties) + .All(pair => + pair.First.Key == pair.Second.Key && + pair.First.Value.Equals(pair.Second.Value) + ); } - public override int GetHashCode() => - _hasher.Visit(this); - - public override string ToString() => - _serializer.Visit(this); + return obj is NullType; } - public record PropertyType(string Id, Type Type); -} \ No newline at end of file + public override int GetHashCode() => + _hasher.Visit(this); + + public override string ToString() => + _serializer.Visit(this); +} + +public record PropertyType(string Id, Type Type); \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/Type.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Type.cs index 8a94202d..af354e86 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/Type.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Type.cs @@ -1,49 +1,48 @@ using Interpreter.Lib.IR.CheckSemantics.Types.Visitors; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types +namespace Interpreter.Lib.IR.CheckSemantics.Types; + +public class Type : + IVisitable, + IVisitable, + IVisitable { - public class Type : - IVisitable, - IVisitable, - IVisitable - { - private readonly string _name; + private readonly string _name; - protected Type() - { - } + protected Type() + { + } - public Type(string name) => _name = name; + public Type(string name) => _name = name; - public bool Recursive { get; set; } + public bool Recursive { get; set; } - public virtual Unit Accept(ReferenceResolver visitor) => - visitor.Visit(this); + public virtual Unit Accept(ReferenceResolver visitor) => + visitor.Visit(this); - public virtual string Accept(ObjectTypePrinter visitor) => - visitor.Visit(this); + public virtual string Accept(ObjectTypePrinter visitor) => + visitor.Visit(this); - public virtual int Accept(ObjectTypeHasher visitor) => - visitor.Visit(this); + public virtual int Accept(ObjectTypeHasher visitor) => + visitor.Visit(this); - public override bool Equals(object obj) - { - if (ReferenceEquals(this, obj)) return true; - if (obj == null || GetType() != obj.GetType()) return false; - var that = (Type) obj; - return Equals(_name, that._name); - } + public override bool Equals(object obj) + { + if (ReferenceEquals(this, obj)) return true; + if (obj == null || GetType() != obj.GetType()) return false; + var that = (Type) obj; + return Equals(_name, that._name); + } - public override int GetHashCode() => - _name.GetHashCode(); + public override int GetHashCode() => + _name.GetHashCode(); - public override string ToString() => _name; + public override string ToString() => _name; - public static implicit operator Type(string alias) => new(alias); + public static implicit operator Type(string alias) => new(alias); - public static bool operator ==(Type left, Type right) => Equals(left, right); + public static bool operator ==(Type left, Type right) => Equals(left, right); - public static bool operator !=(Type left, Type right) => !(left == right); - } + public static bool operator !=(Type left, Type right) => !(left == right); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs b/Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs index 75162cac..7f78bc92 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/TypeUtils.cs @@ -1,46 +1,43 @@ -using System.Collections.Generic; +namespace Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Types +public static class TypeUtils { - public static class TypeUtils - { - public static ( - Type Number, Type Boolean, Type String, Type Null, Type Undefined, Type Void - ) JavaScriptTypes { get; } = ( - new Type("number"), - new Type("boolean"), - new Type("string"), - new NullType(), - new Type("undefined"), - new Type("void") - ); + public static ( + Type Number, Type Boolean, Type String, Type Null, Type Undefined, Type Void + ) JavaScriptTypes { get; } = ( + new Type("number"), + new Type("boolean"), + new Type("string"), + new NullType(), + new Type("undefined"), + new Type("void") + ); - public static object GetDefaultValue(Type type) - { - if (type.Equals(JavaScriptTypes.Boolean)) - return false; - if (type.Equals(JavaScriptTypes.Number)) - return 0; - if (type.Equals(JavaScriptTypes.String)) - return ""; - if (type.Equals(JavaScriptTypes.Void)) - return new Void(); - if (type.Equals(JavaScriptTypes.Null)) - return null; - if (type is ArrayType) - return new List(); + public static object GetDefaultValue(Type type) + { + if (type.Equals(JavaScriptTypes.Boolean)) + return false; + if (type.Equals(JavaScriptTypes.Number)) + return 0; + if (type.Equals(JavaScriptTypes.String)) + return ""; + if (type.Equals(JavaScriptTypes.Void)) + return new Void(); + if (type.Equals(JavaScriptTypes.Null)) + return null; + if (type is ArrayType) + return new List(); - return new Undefined(); - } + return new Undefined(); + } - public struct Undefined - { - public override string ToString() => JavaScriptTypes.Undefined.ToString(); - } + public struct Undefined + { + public override string ToString() => JavaScriptTypes.Undefined.ToString(); + } - private struct Void - { - public override string ToString() => JavaScriptTypes.Void.ToString(); - } + private struct Void + { + public override string ToString() => JavaScriptTypes.Void.ToString(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypeHasher.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypeHasher.cs index df858b27..ef33b5ef 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypeHasher.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypeHasher.cs @@ -1,52 +1,49 @@ -using System; -using System.Linq; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors +namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors; + +public class ObjectTypeHasher : + IVisitor, + IVisitor, + IVisitor, + IVisitor, + IVisitor { - public class ObjectTypeHasher : - IVisitor, - IVisitor, - IVisitor, - IVisitor, - IVisitor - { - private readonly ObjectType _reference; + private readonly ObjectType _reference; - public ObjectTypeHasher(ObjectType reference) => - _reference = reference; + public ObjectTypeHasher(ObjectType reference) => + _reference = reference; - public int Visit(Type visitable) => - visitable.GetHashCode(); - - public int Visit(ObjectType visitable) => - visitable.Keys.Select(key => HashCode.Combine(key, - visitable[key].Equals(_reference) - ? "@this".GetHashCode() - : visitable[key].Recursive - ? key.GetHashCode() - : visitable[key].Accept(this)) - ).Aggregate(36, HashCode.Combine); + public int Visit(Type visitable) => + visitable.GetHashCode(); - public int Visit(ArrayType visitable) => - visitable.Type.Equals(_reference) + public int Visit(ObjectType visitable) => + visitable.Keys.Select(key => HashCode.Combine(key, + visitable[key].Equals(_reference) ? "@this".GetHashCode() - : visitable.Type.Accept(this); + : visitable[key].Recursive + ? key.GetHashCode() + : visitable[key].Accept(this)) + ).Aggregate(36, HashCode.Combine); - public int Visit(NullableType visitable) => - visitable.Type.Equals(_reference) - ? "@this".GetHashCode() - : visitable.Type.Accept(this); + public int Visit(ArrayType visitable) => + visitable.Type.Equals(_reference) + ? "@this".GetHashCode() + : visitable.Type.Accept(this); + + public int Visit(NullableType visitable) => + visitable.Type.Equals(_reference) + ? "@this".GetHashCode() + : visitable.Type.Accept(this); - public int Visit(FunctionType visitable) => - HashCode.Combine( - visitable.ReturnType.Equals(_reference) + public int Visit(FunctionType visitable) => + HashCode.Combine( + visitable.ReturnType.Equals(_reference) + ? "@this".GetHashCode() + : visitable.ReturnType.Accept(this), + visitable.Arguments.Select(arg => + arg.Equals(_reference) ? "@this".GetHashCode() - : visitable.ReturnType.Accept(this), - visitable.Arguments.Select(arg => - arg.Equals(_reference) - ? "@this".GetHashCode() - : arg.Accept(this) - ).Aggregate(36, HashCode.Combine)); - } + : arg.Accept(this) + ).Aggregate(36, HashCode.Combine)); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs index 4567fd08..1f11d91a 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ObjectTypePrinter.cs @@ -1,77 +1,75 @@ -using System.Linq; using System.Text; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors +namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors; + +public class ObjectTypePrinter : + IVisitor, + IVisitor, + IVisitor, + IVisitor, + IVisitor { - public class ObjectTypePrinter : - IVisitor, - IVisitor, - IVisitor, - IVisitor, - IVisitor - { - private readonly ObjectType _reference; + private readonly ObjectType _reference; - public ObjectTypePrinter(ObjectType reference) => - _reference = reference; + public ObjectTypePrinter(ObjectType reference) => + _reference = reference; - public string Visit(Type visitable) => - visitable.ToString(); + public string Visit(Type visitable) => + visitable.ToString(); - public string Visit(ObjectType visitable) + public string Visit(ObjectType visitable) + { + var sb = new StringBuilder("{"); + foreach (var key in visitable.Keys) { - var sb = new StringBuilder("{"); - foreach (var key in visitable.Keys) - { - var type = visitable[key]; - var prop = $"{key}: "; - prop += type.Equals(_reference) - ? "@this" - : type.Recursive - ? key - : type.Accept(this); - sb.Append(prop).Append(';'); - } - - return sb.Append('}').ToString(); + var type = visitable[key]; + var prop = $"{key}: "; + prop += type.Equals(_reference) + ? "@this" + : type.Recursive + ? key + : type.Accept(this); + sb.Append(prop).Append(';'); } - public string Visit(ArrayType visitable) - { - var sb = new StringBuilder(); - sb.Append(visitable.Type.Equals(_reference) - ? "@this" - : visitable.Type.Accept(this) - ); + return sb.Append('}').ToString(); + } - return sb.Append("[]").ToString(); - } + public string Visit(ArrayType visitable) + { + var sb = new StringBuilder(); + sb.Append(visitable.Type.Equals(_reference) + ? "@this" + : visitable.Type.Accept(this) + ); + + return sb.Append("[]").ToString(); + } - public string Visit(NullableType visitable) - { - var sb = new StringBuilder(); - sb.Append(visitable.Type.Equals(_reference) - ? "@this" - : visitable.Type.Accept(this) - ); + public string Visit(NullableType visitable) + { + var sb = new StringBuilder(); + sb.Append(visitable.Type.Equals(_reference) + ? "@this" + : visitable.Type.Accept(this) + ); - return sb.Append('?').ToString(); - } + return sb.Append('?').ToString(); + } - public string Visit(FunctionType visitable) - { - var sb = new StringBuilder("("); - sb.AppendJoin(", ", visitable.Arguments.Select(x => x.Equals(_reference) - ? "@this" - : x.Accept(this) - )).Append(") => "); - sb.Append(visitable.ReturnType.Equals(_reference) - ? "@this" - : visitable.ReturnType.Accept(this) - ); + public string Visit(FunctionType visitable) + { + var sb = new StringBuilder("("); + sb.AppendJoin(", ", visitable.Arguments.Select(x => x.Equals(_reference) + ? "@this" + : x.Accept(this) + )).Append(") => "); + sb.Append(visitable.ReturnType.Equals(_reference) + ? "@this" + : visitable.ReturnType.Accept(this) + ); - return sb.ToString(); - } + return sb.ToString(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs index 618f5b3e..e7dc86ba 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Types/Visitors/ReferenceResolver.cs @@ -1,77 +1,75 @@ -using System.Collections.Generic; using Visitor.NET.Lib.Core; -namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors -{ - public class ReferenceResolver : - IVisitor, - IVisitor, - IVisitor, - IVisitor, - IVisitor - { - private readonly ObjectType _reference; - private readonly string _refId; - private readonly HashSet _visited; +namespace Interpreter.Lib.IR.CheckSemantics.Types.Visitors; - public ReferenceResolver(ObjectType reference, string refId) - { - _reference = reference; - _refId = refId; - _visited = new(); - } - - public Unit Visit(ObjectType visitable) - { - if (_visited.Contains(visitable)) - return default; - _visited.Add(visitable); - - foreach (var key in visitable.Keys) - if (_refId == visitable[key]) - visitable[key] = _reference; - else - visitable[key].Accept(this); - return default; - } +public class ReferenceResolver : + IVisitor, + IVisitor, + IVisitor, + IVisitor, + IVisitor +{ + private readonly ObjectType _reference; + private readonly string _refId; + private readonly HashSet _visited; - public Unit Visit(Type visitable) => default; + public ReferenceResolver(ObjectType reference, string refId) + { + _reference = reference; + _refId = refId; + _visited = new(); + } - public Unit Visit(ArrayType visitable) - { - if (visitable.Type == _refId) - visitable.Type = _reference; - else - visitable.Type.Accept(this); + public Unit Visit(ObjectType visitable) + { + if (_visited.Contains(visitable)) return default; - } - - public Unit Visit(FunctionType visitable) - { - if (visitable.ReturnType == _refId) - visitable.ReturnType = _reference; + _visited.Add(visitable); + + foreach (var key in visitable.Keys) + if (_refId == visitable[key]) + visitable[key] = _reference; else - visitable.ReturnType.Accept(this); + visitable[key].Accept(this); + return default; + } - for (var i = 0; i < visitable.Arguments.Count; i++) - { - var argType = visitable.Arguments[i]; - if (argType == _refId) - visitable.Arguments[i] = _reference; - else - argType.Accept(this); - } + public Unit Visit(Type visitable) => default; + + public Unit Visit(ArrayType visitable) + { + if (visitable.Type == _refId) + visitable.Type = _reference; + else + visitable.Type.Accept(this); + return default; + } - return default; - } + public Unit Visit(FunctionType visitable) + { + if (visitable.ReturnType == _refId) + visitable.ReturnType = _reference; + else + visitable.ReturnType.Accept(this); - public Unit Visit(NullableType visitable) + for (var i = 0; i < visitable.Arguments.Count; i++) { - if (visitable.Type == _refId) - visitable.Type = _reference; + var argType = visitable.Arguments[i]; + if (argType == _refId) + visitable.Arguments[i] = _reference; else - visitable.Type.Accept(this); - return default; + argType.Accept(this); } + + return default; + } + + public Unit Visit(NullableType visitable) + { + if (visitable.Type == _refId) + visitable.Type = _reference; + else + visitable.Type.Accept(this); + return default; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs index 8b79e860..2a7d33f4 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTable.cs @@ -1,46 +1,43 @@ -using System.Collections.Generic; using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Lib.IR.CheckSemantics.Variables +namespace Interpreter.Lib.IR.CheckSemantics.Variables; + +public class SymbolTable { - public class SymbolTable - { - private readonly Dictionary _symbols = new(); - private readonly Dictionary _types = new(); + private readonly Dictionary _symbols = new(); + private readonly Dictionary _types = new(); - private SymbolTable _openScope; + private SymbolTable _openScope; - public void AddOpenScope(SymbolTable table) - { - _openScope = table; - } + public void AddOpenScope(SymbolTable table) + { + _openScope = table; + } - public void AddSymbol(Symbol symbol) => _symbols[symbol.Id] = symbol; + public void AddSymbol(Symbol symbol) => _symbols[symbol.Id] = symbol; - public void AddType(Type type, string typeId = null) => - _types[typeId ?? type.ToString()] = type; + public void AddType(Type type, string typeId = null) => + _types[typeId ?? type.ToString()] = type; - public Type FindType(string typeId) - { - var hasInsideTheScope = _types.TryGetValue(typeId, out var type); - return !hasInsideTheScope ? _openScope?.FindType(typeId) : type; - } - - /// - /// Поиск эффективного символа - /// - public T FindSymbol(string id) where T : Symbol - { - var hasInsideTheScope = _symbols.TryGetValue(id, out var symbol); - return !hasInsideTheScope ? _openScope?.FindSymbol(id) : symbol as T; - } - - /// - /// Проверяет наличие собственного символа - /// - public bool ContainsSymbol(string id) => _symbols.ContainsKey(id); - - public void Clear() => _symbols.Clear(); + public Type FindType(string typeId) + { + var hasInsideTheScope = _types.TryGetValue(typeId, out var type); + return !hasInsideTheScope ? _openScope?.FindType(typeId) : type; } + + /// + /// Поиск эффективного символа + /// + public T FindSymbol(string id) where T : Symbol + { + var hasInsideTheScope = _symbols.TryGetValue(id, out var symbol); + return !hasInsideTheScope ? _openScope?.FindSymbol(id) : symbol as T; + } + + /// + /// Проверяет наличие собственного символа + /// + public bool ContainsSymbol(string id) => _symbols.ContainsKey(id); + + public void Clear() => _symbols.Clear(); } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs index 97e42065..b9b228da 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/SymbolTableUtils.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using Interpreter.Lib.FrontEnd.GetTokens.Data; using Interpreter.Lib.IR.Ast.Nodes; using Interpreter.Lib.IR.Ast.Nodes.Declarations; @@ -6,48 +5,47 @@ using Interpreter.Lib.IR.CheckSemantics.Types; using Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.IR.CheckSemantics.Variables +namespace Interpreter.Lib.IR.CheckSemantics.Variables; + +public static class SymbolTableUtils { - public static class SymbolTableUtils + public static SymbolTable GetStandardLibrary() { - public static SymbolTable GetStandardLibrary() - { - var library = new SymbolTable(); + var library = new SymbolTable(); - library.AddType(TypeUtils.JavaScriptTypes.Number); - library.AddType(TypeUtils.JavaScriptTypes.Boolean); - library.AddType(TypeUtils.JavaScriptTypes.String); - library.AddType(TypeUtils.JavaScriptTypes.Null); - library.AddType(TypeUtils.JavaScriptTypes.Void); + library.AddType(TypeUtils.JavaScriptTypes.Number); + library.AddType(TypeUtils.JavaScriptTypes.Boolean); + library.AddType(TypeUtils.JavaScriptTypes.String); + library.AddType(TypeUtils.JavaScriptTypes.Null); + library.AddType(TypeUtils.JavaScriptTypes.Void); - var print = new FunctionSymbol( - "print", - new List - { - new VariableSymbol("str", TypeUtils.JavaScriptTypes.String) - }, - new FunctionType(TypeUtils.JavaScriptTypes.Void, new[] {TypeUtils.JavaScriptTypes.String}) - ); - print.Body = new FunctionDeclaration( - print, - new BlockStatement(new List()) - { - SymbolTable = new SymbolTable() - } - ) + var print = new FunctionSymbol( + "print", + new List { - SymbolTable = new SymbolTable(), - Segment = new Segment( - new Coordinates(0, 0), - new Coordinates(0, 0) - ) - }; + new VariableSymbol("str", TypeUtils.JavaScriptTypes.String) + }, + new FunctionType(TypeUtils.JavaScriptTypes.Void, new[] {TypeUtils.JavaScriptTypes.String}) + ); + print.Body = new FunctionDeclaration( + print, + new BlockStatement(new List()) + { + SymbolTable = new SymbolTable() + } + ) + { + SymbolTable = new SymbolTable(), + Segment = new Segment( + new Coordinates(0, 0), + new Coordinates(0, 0) + ) + }; - library.AddSymbol(print); + library.AddSymbol(print); - var symbolTable = new SymbolTable(); - symbolTable.AddOpenScope(library); - return symbolTable; - } + var symbolTable = new SymbolTable(); + symbolTable.AddOpenScope(library); + return symbolTable; } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs index 1cc2f38c..a7144623 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/FunctionSymbol.cs @@ -1,35 +1,33 @@ -using System.Collections.Generic; using System.Text; using Interpreter.Lib.BackEnd; using Interpreter.Lib.IR.Ast.Nodes.Declarations; using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; + +public class FunctionSymbol : Symbol { - public class FunctionSymbol : Symbol - { - public override FunctionType Type { get; } + public override FunctionType Type { get; } - public List Parameters { get; } + public List Parameters { get; } - public FunctionDeclaration Body { get; set; } + public FunctionDeclaration Body { get; set; } - public FunctionInfo CallInfo { get; } + public FunctionInfo CallInfo { get; } - public FunctionSymbol(string id, IEnumerable parameters, FunctionType type) : - base(id, type) - { - Parameters = new List(parameters); - CallInfo = new FunctionInfo(id); - Type = type; - } + public FunctionSymbol(string id, IEnumerable parameters, FunctionType type) : + base(id, type) + { + Parameters = new List(parameters); + CallInfo = new FunctionInfo(id); + Type = type; + } - public override string ToString() - { - var sb = new StringBuilder($"function {Id}("); - sb.AppendJoin(',', Parameters); - sb.Append($") => {Type.ReturnType}"); - return sb.ToString(); - } + public override string ToString() + { + var sb = new StringBuilder($"function {Id}("); + sb.AppendJoin(',', Parameters); + sb.Append($") => {Type.ReturnType}"); + return sb.ToString(); } } \ No newline at end of file diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs index 5f3906d3..efb9672e 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/ObjectSymbol.cs @@ -1,26 +1,25 @@ using Interpreter.Lib.IR.CheckSemantics.Types; -namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; + +public class ObjectSymbol : VariableSymbol { - public class ObjectSymbol : VariableSymbol - { - public override ObjectType Type { get; } + public override ObjectType Type { get; } - public SymbolTable Table { get; init; } + public SymbolTable Table { get; init; } - public ObjectSymbol(string id, ObjectType objectType, bool readOnly = false, SymbolTable table = null) : - base(id, objectType, readOnly) + public ObjectSymbol(string id, ObjectType objectType, bool readOnly = false, SymbolTable table = null) : + base(id, objectType, readOnly) + { + Type = objectType; + if (table != null) { - Type = objectType; - if (table != null) + foreach (var key in objectType.Keys) { - foreach (var key in objectType.Keys) + if (objectType[key] is FunctionType) { - if (objectType[key] is FunctionType) - { - var function = table.FindSymbol(key); - function.CallInfo.MethodOf = id; - } + var function = table.FindSymbol(key); + function.CallInfo.MethodOf = id; } } } diff --git a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs index 8a14e05a..87b487c8 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/Symbol.cs @@ -1,15 +1,12 @@ -using Interpreter.Lib.IR.CheckSemantics.Types; +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols +public abstract class Symbol { - public abstract class Symbol - { - // ReSharper disable once VirtualMemberNeverOverridden.Global - public virtual string Id { get; } + // ReSharper disable once VirtualMemberNeverOverridden.Global + public virtual string Id { get; } - public virtual Type Type { get; } + public virtual Type Type { get; } - protected Symbol(string id, Type type) => - (Id, Type) = (id, type); - } + 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 index 37e29f0e..9ef2db85 100644 --- a/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/VariableSymbol.cs +++ b/Interpreter.Lib/IR/CheckSemantics/Variables/Symbols/VariableSymbol.cs @@ -1,15 +1,12 @@ -using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; +namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols; -namespace Interpreter.Lib.IR.CheckSemantics.Variables.Symbols +public class VariableSymbol : Symbol { - public class VariableSymbol : Symbol - { - public bool ReadOnly { get; } + public bool ReadOnly { get; } - public VariableSymbol(string id, Type type, bool readOnly = false) : - base(id, type) => - ReadOnly = readOnly; + public VariableSymbol(string id, Type type, bool readOnly = false) : + base(id, type) => + ReadOnly = readOnly; - public override string ToString() => $"{(ReadOnly ? "const " : "")}{Id}: {Type}"; - } + public override string ToString() => $"{(ReadOnly ? "const " : "")}{Id}: {Type}"; } \ No newline at end of file diff --git a/Interpreter.Lib/Interpreter.Lib.csproj b/Interpreter.Lib/Interpreter.Lib.csproj index 7493e3a2..c81edfde 100644 --- a/Interpreter.Lib/Interpreter.Lib.csproj +++ b/Interpreter.Lib/Interpreter.Lib.csproj @@ -1,7 +1,8 @@ - net6.0 + net7.0 + enable diff --git a/Interpreter.Tests/GlobalUsings.cs b/Interpreter.Tests/GlobalUsings.cs new file mode 100644 index 00000000..9f96c142 --- /dev/null +++ b/Interpreter.Tests/GlobalUsings.cs @@ -0,0 +1,3 @@ +// Global using directives + +global using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; \ No newline at end of file diff --git a/Interpreter.Tests/Interpreter.Tests.csproj b/Interpreter.Tests/Interpreter.Tests.csproj index 19f1a28c..4a4d264c 100644 --- a/Interpreter.Tests/Interpreter.Tests.csproj +++ b/Interpreter.Tests/Interpreter.Tests.csproj @@ -1,24 +1,29 @@ - net6.0 - + net7.0 false + enable + + + + true + cobertura - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Interpreter.Tests/MockExtensions.cs b/Interpreter.Tests/MockExtensions.cs index 86a3319b..9c9b4c6d 100644 --- a/Interpreter.Tests/MockExtensions.cs +++ b/Interpreter.Tests/MockExtensions.cs @@ -3,20 +3,32 @@ using Microsoft.Extensions.Options; using Moq; -namespace Interpreter.Tests +namespace Interpreter.Tests; + +public static class MockExtensions { - 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; + } + + public static IOptions ToOptions + (this Mock commandLineSettings) => + Options.Create(commandLineSettings.Object); + + public static Mock ToInstructionMock(this int number) { - public static Mock Trackable(this Mock halt) + var result = new Mock(MockBehavior.Default, number) { - halt.Setup(x => x.Execute(It.IsAny())) - .Returns(-3).Verifiable(); - halt.Setup(x => x.End()).Returns(true); - return halt; - } + CallBase = true + }; + + result.Setup(x => x.ToString()) + .Returns(number.ToString()); - public static IOptions ToOptions - (this Mock commandLineSettings) => - Options.Create(commandLineSettings.Object); + return result; } } \ No newline at end of file diff --git a/Interpreter.Tests/Stubs/SemanticExceptionStub.cs b/Interpreter.Tests/Stubs/SemanticExceptionStub.cs index 84e616a1..c1cc2463 100644 --- a/Interpreter.Tests/Stubs/SemanticExceptionStub.cs +++ b/Interpreter.Tests/Stubs/SemanticExceptionStub.cs @@ -1,6 +1,5 @@ using Interpreter.Lib.IR.CheckSemantics.Exceptions; -namespace Interpreter.Tests.Stubs -{ - public class SemanticExceptionStub : SemanticException { } -} \ No newline at end of file +namespace Interpreter.Tests.Stubs; + +public class SemanticExceptionStub : SemanticException { } \ No newline at end of file diff --git a/Interpreter.Tests/TestData/InstructionsData.cs b/Interpreter.Tests/TestData/InstructionsData.cs index 02e3e607..2eb25f8b 100644 --- a/Interpreter.Tests/TestData/InstructionsData.cs +++ b/Interpreter.Tests/TestData/InstructionsData.cs @@ -1,107 +1,105 @@ 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 +namespace Interpreter.Tests.TestData; + +public class InstructionsData : IEnumerable { - public class InstructionsData : IEnumerable + public IEnumerator GetEnumerator() { - 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(); + 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 index b597294c..a6addcfb 100644 --- a/Interpreter.Tests/TestData/LexerData.cs +++ b/Interpreter.Tests/TestData/LexerData.cs @@ -1,29 +1,27 @@ using System.Collections; -using System.Collections.Generic; -namespace Interpreter.Tests.TestData +namespace Interpreter.Tests.TestData; + +public class LexerSuccessData : IEnumerable { - public class LexerSuccessData : IEnumerable + public IEnumerator GetEnumerator() { - 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(); + yield return new object[] { "a + b - c return while do" }; + yield return new object[] { "=> abc null true false" }; + yield return new object[] { "{ . } , ( ) [] =?:" }; } - 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(); +} - 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/ParserData.cs b/Interpreter.Tests/TestData/ParserData.cs index cc0cbe1d..8a9cda65 100644 --- a/Interpreter.Tests/TestData/ParserData.cs +++ b/Interpreter.Tests/TestData/ParserData.cs @@ -1,20 +1,18 @@ using System.Collections; -using System.Collections.Generic; -namespace Interpreter.Tests.TestData +namespace Interpreter.Tests.TestData; + +public class ParserSuccessTestData : IEnumerable { - public class ParserSuccessTestData : IEnumerable + public IEnumerator GetEnumerator() { - public IEnumerator GetEnumerator() - { - yield return new object[] {"i[0].j"}; - yield return new object[] {"i[0].j()"}; - yield return new object[] {"i = 1"}; - yield return new object[] {"i[0] = 1"}; - yield return new object[] {"i[a.b][1].x(1)"}; - yield return new object[] {"(1 + 2) * (3 - (2 / 2)) as string"}; - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + yield return new object[] {"i[0].j"}; + yield return new object[] {"i[0].j()"}; + yield return new object[] {"i = 1"}; + yield return new object[] {"i[0] = 1"}; + yield return new object[] {"i[a.b][1].x(1)"}; + yield return new object[] {"(1 + 2) * (3 - (2 / 2)) as string"}; } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/BackEnd/AddressedInstructionsTests.cs b/Interpreter.Tests/Unit/BackEnd/AddressedInstructionsTests.cs new file mode 100644 index 00000000..6b38d5ab --- /dev/null +++ b/Interpreter.Tests/Unit/BackEnd/AddressedInstructionsTests.cs @@ -0,0 +1,69 @@ +using Interpreter.Lib.BackEnd; +using Interpreter.Lib.BackEnd.Instructions; +using Interpreter.Lib.BackEnd.Values; +using Xunit; + +namespace Interpreter.Tests.Unit.BackEnd; + +public class AddressedInstructionsTests +{ + private readonly AddressedInstructions _collection = new(); + + [Fact] + public void EnumerationPreservedAfterRemovalTest() + { + var instructions = new List + { + new AsString("s", new Constant(2, "2"), 0), + new Print(1, new Name("s")), + new Halt(2) + }; + + _collection.AddRange(instructions); + + _collection.Remove(instructions[1]); + + Assert.Same(instructions[2], _collection[instructions[0].Address.Next]); + } + + [Fact] + public void RemovalOfLastDoesNotThrow() + { + var instructions = new List + { + new AsString("s", new Constant(2, "2"), 0), + new Halt(2) + }; + + instructions.ForEach(instruction => _collection.Add(instruction)); + + Assert.Null(Record.Exception(() => _collection.Remove(instructions[1]))); + Assert.Null(instructions[0].Address.Next); + } + + [Fact] + public void GetEnumeratorTests() + { + _collection.Add(1.ToInstructionMock().Object); + + var collectionToAdd = new AddressedInstructions + { + 2.ToInstructionMock().Object, + 3.ToInstructionMock().Object, + 4.ToInstructionMock().Object + }; + + _collection.AddRange(collectionToAdd); + + _collection.Add(5.ToInstructionMock().Object); + + Assert.Collection( + _collection.Select(x => x.ToString()), + x => Assert.Equal("1", x), + x => Assert.Equal("2", x), + x => Assert.Equal("3", x), + x => Assert.Equal("4", x), + x => Assert.Equal("5", x) + ); + } +} \ No newline at end of file diff --git a/Interpreter.Tests/Unit/BackEnd/CallTests.cs b/Interpreter.Tests/Unit/BackEnd/CallTests.cs index c07c6a21..48571a99 100644 --- a/Interpreter.Tests/Unit/BackEnd/CallTests.cs +++ b/Interpreter.Tests/Unit/BackEnd/CallTests.cs @@ -1,22 +1,20 @@ -using System.Collections.Generic; using Interpreter.Lib.BackEnd; using Xunit; -namespace Interpreter.Tests.Unit.BackEnd +namespace Interpreter.Tests.Unit.BackEnd; + +public class CallTests { - public class CallTests + [Fact] + public void ToStringCorrect() { - [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()); - } + 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 index bc236e7a..f0fc3116 100644 --- a/Interpreter.Tests/Unit/BackEnd/FunctionInfoTests.cs +++ b/Interpreter.Tests/Unit/BackEnd/FunctionInfoTests.cs @@ -1,14 +1,13 @@ using Interpreter.Lib.BackEnd; using Xunit; -namespace Interpreter.Tests.Unit.BackEnd +namespace Interpreter.Tests.Unit.BackEnd; + +public class FunctionInfoTests { - 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()); - } + [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 index 919e4b82..6111c5d7 100644 --- a/Interpreter.Tests/Unit/BackEnd/InstructionsTests.cs +++ b/Interpreter.Tests/Unit/BackEnd/InstructionsTests.cs @@ -3,38 +3,37 @@ using Moq; using Xunit; -namespace Interpreter.Tests.Unit.BackEnd +namespace Interpreter.Tests.Unit.BackEnd; + +public class InstructionsTests { - public class InstructionsTests - { - [Theory] - [ClassData(typeof(InstructionsData))] - public void ToStringCorrectTest(Instruction instruction, string expected) => - Assert.Equal(expected, instruction.ToString()); + [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; + [Fact] + public void ComparisonDependsOnAddressTest() + { + var instruction1 = new Mock(1).Object; + var instruction2 = new Mock(2).Object; - Assert.Equal(1, instruction2.CompareTo(instruction1)); - } + 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 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); - } + [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 index b5535349..20dc7dc6 100644 --- a/Interpreter.Tests/Unit/BackEnd/ValuesTests.cs +++ b/Interpreter.Tests/Unit/BackEnd/ValuesTests.cs @@ -1,46 +1,45 @@ using Interpreter.Lib.BackEnd.Values; using Xunit; -namespace Interpreter.Tests.Unit.BackEnd +namespace Interpreter.Tests.Unit.BackEnd; + +public class ValuesTests { - public class ValuesTests + [Fact] + public void ConstantNotEqualToNameTest() { - [Fact] - public void ConstantNotEqualToNameTest() - { - var name = new Name("a"); - var constant = new Constant("a", "a"); + var name = new Name("a"); + var constant = new Constant("a", "a"); - Assert.False(name.Equals(constant)); - Assert.False(constant.Equals(name)); - } + 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"); + [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()); - } + 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"); + [Fact] + public void NameEqualsCorrectTest() + { + var name1 = new Name("name"); + var name2 = new Name("name"); - Assert.True(name1.Equals(name2)); - } + Assert.True(name1.Equals(name2)); + } - [Fact] - public void ConstantEqualsCorrectTest() - { - var constant1 = new Constant(1, "1"); - var constant2 = new Constant(1, "1.0"); + [Fact] + public void ConstantEqualsCorrectTest() + { + var constant1 = new Constant(1, "1"); + var constant2 = new Constant(1, "1.0"); - Assert.True(constant1.Equals(constant2)); - } + 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 index 52794a4a..28a8234e 100644 --- a/Interpreter.Tests/Unit/BackEnd/VirtualMachineTests.cs +++ b/Interpreter.Tests/Unit/BackEnd/VirtualMachineTests.cs @@ -1,135 +1,131 @@ #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 +namespace Interpreter.Tests.Unit.BackEnd; + +public class VirtualMachineTests { - public class VirtualMachineTests - { - private readonly VirtualMachine _vm; + private readonly VirtualMachine _vm; - public VirtualMachineTests() - { - _vm = new(new(), new(), new(), TextWriter.Null); - } + 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(); + [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")); + 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()); - } + 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)); + [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))); - } + program.Add(new Halt(0)); + Assert.Null(Record.Exception(() => _vm.Run(program))); + } - [Fact] - public void VirtualMachineFramesClearedAfterExecutionTest() + [Fact] + public void VirtualMachineFramesClearedAfterExecutionTest() + { + var program = new List() { - 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) - }; + 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); - } + _vm.Run(program); + Assert.Empty(_vm.Frames); + } - [Fact] - public void VirtualMachineHandlesRecursionTest() + [Fact] + public void VirtualMachineHandlesRecursionTest() + { + var halt = new Mock(12).Trackable(); + var factorial = new FunctionInfo("fact", 1); + var program = new List { - 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 - }; + 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(); - } + _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()); + [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 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 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); - } + 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() + [Fact] + public void ObjectCreationTest() + { + var halt = new Mock(2).Trackable(); + var program = new List { - 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 - }; + 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(); - } + _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 index 3d0cc052..fe187cb8 100644 --- a/Interpreter.Tests/Unit/FrontEnd/LexerTests.cs +++ b/Interpreter.Tests/Unit/FrontEnd/LexerTests.cs @@ -1,52 +1,50 @@ -using System.Linq; using Interpreter.Lib.FrontEnd.GetTokens; using Interpreter.Lib.FrontEnd.GetTokens.Impl; using Interpreter.Services.Providers.Impl.StructureProvider; using Interpreter.Tests.TestData; using Xunit; -namespace Interpreter.Tests.Unit.FrontEnd +namespace Interpreter.Tests.Unit.FrontEnd; + +public class LexerTests { - public class LexerTests + private readonly Lexer _lexer; + + public LexerTests() + { + _lexer = new Lexer(new StructureProvider().CreateStructure()); + } + + [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("")); + + [Fact] + public void GetTokensSkipIgnorableTypesTest() { - private readonly Lexer _lexer; - - public LexerTests() - { - _lexer = new Lexer(new StructureProvider().CreateStructure()); - } - - [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("")); - - [Fact] - public void GetTokensSkipIgnorableTypesTest() - { - const string text = @" + const string text = @" let x = 1 // int "; - var tokens = _lexer.GetTokens(text); - Assert.DoesNotContain(_lexer.Structure.FindByTag("Comment"), tokens.Select(x => x.Type)); - } + var tokens = _lexer.GetTokens(text); + Assert.DoesNotContain(_lexer.Structure.FindByTag("Comment"), tokens.Select(x => x.Type)); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs b/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs index 4700d075..2628b567 100644 --- a/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs +++ b/Interpreter.Tests/Unit/FrontEnd/ParserTests.cs @@ -5,30 +5,29 @@ using Interpreter.Tests.TestData; using Xunit; -namespace Interpreter.Tests.Unit.FrontEnd +namespace Interpreter.Tests.Unit.FrontEnd; + +public class ParserTests { - public class ParserTests - { - private readonly IParser _parser; + private readonly IParser _parser; - public ParserTests() - { - _parser = new Parser(new Lexer( - new StructureProvider() - .CreateStructure() - )); - } + public ParserTests() + { + _parser = new Parser(new Lexer( + new StructureProvider() + .CreateStructure() + )); + } - [Theory] - [ClassData(typeof(ParserSuccessTestData))] - public void ParserDoesNotThrowTest(string text) + [Theory] + [ClassData(typeof(ParserSuccessTestData))] + public void ParserDoesNotThrowTest(string text) + { + var ex = Record.Exception(() => { - var ex = Record.Exception(() => - { - // ReSharper disable once UnusedVariable - var ast = _parser.TopDownParse(text); - }); - Assert.Null(ex); - } + // 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 index 645a8438..9035b6a5 100644 --- a/Interpreter.Tests/Unit/FrontEnd/StructureTests.cs +++ b/Interpreter.Tests/Unit/FrontEnd/StructureTests.cs @@ -1,32 +1,30 @@ -using System.Collections.Generic; using Interpreter.Lib.FrontEnd.GetTokens.Data; using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; using Xunit; -namespace Interpreter.Tests.Unit.FrontEnd +namespace Interpreter.Tests.Unit.FrontEnd; + +public class StructureTests { - public class StructureTests + [Fact] + public void ToStringCorrectTest() { - [Fact] - public void ToStringCorrectTest() + var tokenTypes = new List { - var tokenTypes = new List - { - new ("MyToken", "[m|M][y|Y]", 2), - new ("OneToSeven", "[1-7]", 1) - }; - var structure = new Structure(tokenTypes); + 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()); - } + 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/IR/AstNodeTests.cs b/Interpreter.Tests/Unit/IR/AstNodeTests.cs index be05ddcc..95344cb0 100644 --- a/Interpreter.Tests/Unit/IR/AstNodeTests.cs +++ b/Interpreter.Tests/Unit/IR/AstNodeTests.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using Interpreter.Lib.IR.Ast.Nodes; using Interpreter.Lib.IR.Ast.Nodes.Declarations; using Interpreter.Lib.IR.Ast.Nodes.Statements; @@ -7,25 +6,24 @@ using Moq; using Xunit; -namespace Interpreter.Tests.Unit.IR +namespace Interpreter.Tests.Unit.IR; + +public class AstNodeTests { - public class AstNodeTests + [Fact] + public void PrecedenceTest() { - [Fact] - public void PrecedenceTest() - { - var fType = new Mock(new Mock("").Object, new List()); - var funcSymbol = new FunctionSymbol("f", new List(), fType.Object); + var fType = new Mock(new Mock("").Object, new List()); + var funcSymbol = new FunctionSymbol("f", new List(), fType.Object); - var lexicalDecl = new LexicalDeclaration(false); - var stmtItemList = new List - { - lexicalDecl - }; - // ReSharper disable once UnusedVariable - var func = new FunctionDeclaration(funcSymbol, new BlockStatement(stmtItemList)); + var lexicalDecl = new LexicalDeclaration(false); + var stmtItemList = new List + { + lexicalDecl + }; + // ReSharper disable once UnusedVariable + var func = new FunctionDeclaration(funcSymbol, new BlockStatement(stmtItemList)); - Assert.True(lexicalDecl.ChildOf()); - } + Assert.True(lexicalDecl.ChildOf()); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/IR/ExpressionTests.cs b/Interpreter.Tests/Unit/IR/ExpressionTests.cs index 2fa0ad48..30663b57 100644 --- a/Interpreter.Tests/Unit/IR/ExpressionTests.cs +++ b/Interpreter.Tests/Unit/IR/ExpressionTests.cs @@ -1,24 +1,22 @@ 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.IR +namespace Interpreter.Tests.Unit.IR; + +public class ExpressionTests { - public class ExpressionTests + [Fact] + public void BinaryExpressionTest() { - [Fact] - public void BinaryExpressionTest() - { - var number = new Type("number"); + var number = new Type("number"); - var left = new Literal(number, 0); - var right = new Literal(number, 1); + var left = new Literal(number, 0); + var right = new Literal(number, 1); - var binExpr = new BinaryExpression(left, "-", right); + var binExpr = new BinaryExpression(left, "-", right); - var ex = Record.Exception(() => binExpr.SemanticCheck()); - Assert.Null(ex); - } + var ex = Record.Exception(() => binExpr.SemanticCheck()); + Assert.Null(ex); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/IR/SymbolTableTests.cs b/Interpreter.Tests/Unit/IR/SymbolTableTests.cs index 0a07cb35..d526c30d 100644 --- a/Interpreter.Tests/Unit/IR/SymbolTableTests.cs +++ b/Interpreter.Tests/Unit/IR/SymbolTableTests.cs @@ -1,66 +1,61 @@ -using System; -using System.Collections.Generic; -using System.Linq; 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.IR +namespace Interpreter.Tests.Unit.IR; + +public class SymbolTableTests { - public class SymbolTableTests + [Fact] + public void FindSymbolTest() { - [Fact] - public void FindSymbolTest() - { - const string id = "ident"; - var type = new Mock(id); + const string id = "ident"; + var type = 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 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(); - outerScope.AddSymbol(symbol.Object); - innerScope.AddOpenScope(outerScope); + var outerScope = new SymbolTable(); + var innerScope = new SymbolTable(); + outerScope.AddSymbol(symbol.Object); + innerScope.AddOpenScope(outerScope); - Assert.NotNull(innerScope.FindSymbol(id)); - Assert.True(outerScope.ContainsSymbol(id)); - } + Assert.NotNull(innerScope.FindSymbol(id)); + Assert.True(outerScope.ContainsSymbol(id)); + } - [Fact] - public void FlatteningScopeTest() + [Fact] + public void FlatteningScopeTest() + { + var table = new SymbolTable(); + var stmtList = new List( + Enumerable.Repeat( + new Mock().Object, + new Random().Next(10) + ) + ); + var script = new ScriptBody(stmtList) { - var table = new SymbolTable(); - var stmtList = new List( - Enumerable.Repeat( - new Mock().Object, - new Random().Next(10) - ) - ); - var script = new ScriptBody(stmtList) - { - SymbolTable = table - }; - script.ToList().ForEach(node => node.SymbolTable = table); + SymbolTable = table + }; + script.ToList().ForEach(node => node.SymbolTable = table); - const string id = "ident"; - var type = new Mock(id); + const string id = "ident"; + var type = 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 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); + script.SymbolTable.AddSymbol(symbol.Object); - Assert.All( - script.ToList(), - stmtListItem => - Assert.True(stmtListItem.SymbolTable.ContainsSymbol(id)) - ); - } + Assert.All( + script.ToList(), + stmtListItem => + Assert.True(stmtListItem.SymbolTable.ContainsSymbol(id)) + ); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/IR/Types/ObjectTypeTests.cs b/Interpreter.Tests/Unit/IR/Types/ObjectTypeTests.cs index cf7de8eb..73422c99 100644 --- a/Interpreter.Tests/Unit/IR/Types/ObjectTypeTests.cs +++ b/Interpreter.Tests/Unit/IR/Types/ObjectTypeTests.cs @@ -1,151 +1,147 @@ -using System; -using System.Collections.Generic; using Interpreter.Lib.IR.CheckSemantics.Types; using Xunit; -using Type = Interpreter.Lib.IR.CheckSemantics.Types.Type; -namespace Interpreter.Tests.Unit.IR.Types +namespace Interpreter.Tests.Unit.IR.Types; + +public class ObjectTypeTests { - public class ObjectTypeTests + [Fact] + public void ObjectTypeEqualityTest() { - [Fact] - public void ObjectTypeEqualityTest() - { - var number = new Type("number"); - var p2d1 = new ObjectType( - new PropertyType[] - { - new("x", number), - new("y", number) - } - ); - var p2d2 = new ObjectType( - new PropertyType[] - { - new("y", number), - new("x", number) - } - ); - Assert.Equal(p2d1, p2d2); + var number = new Type("number"); + var p2d1 = new ObjectType( + new PropertyType[] + { + new("x", number), + new("y", number) + } + ); + var p2d2 = new ObjectType( + new PropertyType[] + { + new("y", number), + new("x", number) + } + ); + Assert.Equal(p2d1, p2d2); - var p3d1 = new ObjectType( - new PropertyType[] - { - new("a", number), - new("x", number), - new("y", number) - } - ); - var p3d2 = new ObjectType( - new PropertyType[] - { - new("y", number), - new("x", number), - new("z", number) - } - ); - Assert.NotEqual(p3d1, p3d2); - Assert.NotEqual(p3d2, p2d1); - } + var p3d1 = new ObjectType( + new PropertyType[] + { + new("a", number), + new("x", number), + new("y", number) + } + ); + var p3d2 = new ObjectType( + new PropertyType[] + { + new("y", number), + new("x", number), + new("z", number) + } + ); + Assert.NotEqual(p3d1, p3d2); + Assert.NotEqual(p3d2, p2d1); + } - [Fact] - public void RecursiveTypeReferenceResolvingTest() - { - var number = new Type("number"); - var array = new ArrayType(new Type("self")); - var method = new FunctionType(number, new List { new("self") }); - var nullable = new NullableType(new Type("self")); - var linkedListType = new ObjectType( - new List + [Fact] + public void RecursiveTypeReferenceResolvingTest() + { + var number = new Type("number"); + var array = new ArrayType(new Type("self")); + var method = new FunctionType(number, new List { new("self") }); + var nullable = new NullableType(new Type("self")); + var linkedListType = new ObjectType( + new List + { + new("data", number), + new("wrapped", new ObjectType(new List { - new("data", number), - new("wrapped", new ObjectType(new List - { - new("next", new Type("self")) - })), - new("children", array), - new("parent", nullable), - new("compare", method) - } - ); + new("next", new Type("self")) + })), + new("children", array), + new("parent", nullable), + new("compare", method) + } + ); - linkedListType.ResolveSelfReferences("self"); + linkedListType.ResolveSelfReferences("self"); - Assert.Equal(linkedListType, ((ObjectType)linkedListType["wrapped"])["next"]); - Assert.Equal(linkedListType, array.Type); - Assert.Equal(linkedListType, nullable.Type); - Assert.Equal(linkedListType, method.Arguments[0]); - } + Assert.Equal(linkedListType, ((ObjectType)linkedListType["wrapped"])["next"]); + Assert.Equal(linkedListType, array.Type); + Assert.Equal(linkedListType, nullable.Type); + Assert.Equal(linkedListType, method.Arguments[0]); + } - [Fact] - public void NonSpecifiedTypesVisitingTest() - { - var objectType = new ObjectType( - new List - { - new("any", new Any()), - new("some", new NullType()), - new("next", new Type("self")), - new("prop", new Type("number")) - } - ); - var ex = Record.Exception(() => objectType.ResolveSelfReferences("self")); - Assert.Null(ex); - Assert.Equal(objectType["next"], objectType); - } + [Fact] + public void NonSpecifiedTypesVisitingTest() + { + var objectType = new ObjectType( + new List + { + new("any", new Any()), + new("some", new NullType()), + new("next", new Type("self")), + new("prop", new Type("number")) + } + ); + var ex = Record.Exception(() => objectType.ResolveSelfReferences("self")); + Assert.Null(ex); + Assert.Equal(objectType["next"], objectType); + } - [Fact] - public void ObjectTypeToStringTest() - { - var number = new Type("number"); - var array = new ArrayType(new Type("self")); - var method = new FunctionType(number, new List { new("self") }); - var nullable = new NullableType(new Type("self")); - var linkedListType = new ObjectType( - new List + [Fact] + public void ObjectTypeToStringTest() + { + var number = new Type("number"); + var array = new ArrayType(new Type("self")); + var method = new FunctionType(number, new List { new("self") }); + var nullable = new NullableType(new Type("self")); + var linkedListType = new ObjectType( + new List + { + new("data", number), + new("wrapped", new ObjectType(new List { - new("data", number), - new("wrapped", new ObjectType(new List - { - new("next", new Type("self")) - })), - new("children", array), - new("parent", nullable), - new("compare", method) - } - ); + new("next", new Type("self")) + })), + new("children", array), + new("parent", nullable), + new("compare", method) + } + ); - linkedListType.ResolveSelfReferences("self"); - Assert.Contains("@this", linkedListType.ToString()); - } + linkedListType.ResolveSelfReferences("self"); + Assert.Contains("@this", linkedListType.ToString()); + } - [Fact] - public void SerializationOfTypeWithRecursivePropertyTest() - { - var nodeType = new ObjectType( - new List - { - new("data", new Type("number")), - new("next", new Type("self")) - } - ) { Recursive = true }; - nodeType.ResolveSelfReferences("self"); + [Fact] + public void SerializationOfTypeWithRecursivePropertyTest() + { + var nodeType = new ObjectType( + new List + { + new("data", new Type("number")), + new("next", new Type("self")) + } + ) { Recursive = true }; + nodeType.ResolveSelfReferences("self"); - var linkedListType = new ObjectType( - new List - { - new("head", nodeType), - new("append", new FunctionType( - new Type("void"), - new List { nodeType } - ) - ), - new("copy", new FunctionType(new Type("self"), Array.Empty())) - } - ) { Recursive = true }; - linkedListType.ResolveSelfReferences("self"); + var linkedListType = new ObjectType( + new List + { + new("head", nodeType), + new("append", new FunctionType( + new Type("void"), + new List { nodeType } + ) + ), + new("copy", new FunctionType(new Type("self"), Array.Empty())) + } + ) { Recursive = true }; + linkedListType.ResolveSelfReferences("self"); - Assert.Contains("head: head;", linkedListType.ToString()); - } + Assert.Contains("head: head;", linkedListType.ToString()); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/IR/Types/TypeTests.cs b/Interpreter.Tests/Unit/IR/Types/TypeTests.cs index 04b874a5..1593de75 100644 --- a/Interpreter.Tests/Unit/IR/Types/TypeTests.cs +++ b/Interpreter.Tests/Unit/IR/Types/TypeTests.cs @@ -1,51 +1,49 @@ -using System.Collections.Generic; using Interpreter.Lib.IR.CheckSemantics.Types; using Xunit; -namespace Interpreter.Tests.Unit.IR.Types +namespace Interpreter.Tests.Unit.IR.Types; + +public class TypeTests { - public class TypeTests + [Fact] + public void TypeEqualityTest() { - [Fact] - public void TypeEqualityTest() - { - var number = new Type("number"); - var arrayOfNumbers = new ArrayType(number); - Assert.False(arrayOfNumbers.Equals(number)); - Assert.False(number.Equals(arrayOfNumbers)); - } + var number = new Type("number"); + var arrayOfNumbers = new ArrayType(number); + Assert.False(arrayOfNumbers.Equals(number)); + Assert.False(number.Equals(arrayOfNumbers)); + } - [Fact] - public void TypeStringRepresentationTest() - { - var matrix = new ArrayType(new ArrayType(new Type("number"))); + [Fact] + public void TypeStringRepresentationTest() + { + var matrix = new ArrayType(new ArrayType(new Type("number"))); - Assert.Equal("number[][]", matrix.ToString()); - } + Assert.Equal("number[][]", matrix.ToString()); + } - [Fact] - public void NullTests() - { - var number = new Type("number"); - // ReSharper disable once SuspiciousTypeConversion.Global - Assert.True(new NullType().Equals(new NullableType(number))); - } + [Fact] + public void NullTests() + { + var number = new Type("number"); + // ReSharper disable once SuspiciousTypeConversion.Global + Assert.True(new NullType().Equals(new NullableType(number))); + } - [Fact] - public void TypeWrappingTest() - { - var str = new Type("string"); - str = new NullableType(str); - str = new ArrayType(str); - Assert.Equal("string?[]", str.ToString()); - } + [Fact] + public void TypeWrappingTest() + { + var str = new Type("string"); + str = new NullableType(str); + str = new ArrayType(str); + Assert.Equal("string?[]", str.ToString()); + } - [Fact] - public void DefaultValueTest() - { - Assert.Null(TypeUtils.GetDefaultValue(new NullableType(new Any()))); - Assert.Null(TypeUtils.GetDefaultValue(new NullType())); - Assert.Null(TypeUtils.GetDefaultValue(new ObjectType(new List()))); - } + [Fact] + public void DefaultValueTest() + { + Assert.Null(TypeUtils.GetDefaultValue(new NullableType(new Any()))); + Assert.Null(TypeUtils.GetDefaultValue(new NullType())); + Assert.Null(TypeUtils.GetDefaultValue(new ObjectType(new List()))); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs b/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs index 3da4c099..3c0d04f3 100644 --- a/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs +++ b/Interpreter.Tests/Unit/Infrastructure/ExecutorTests.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using Interpreter.Lib.BackEnd; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.FrontEnd.GetTokens; @@ -11,86 +9,85 @@ using Moq; using Xunit; -namespace Interpreter.Tests.Unit.Infrastructure +namespace Interpreter.Tests.Unit.Infrastructure; + +public class ExecutorTests { - public class ExecutorTests - { - private readonly Mock _settings; - private readonly Mock _parsingService; + 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"); + public ExecutorTests() + { + _settings = new Mock(); + _settings.Setup(x => x.Dump).Returns(false); + _settings.Setup(x => x.InputFilePath).Returns("file.js"); - _parsingService = new Mock(); - } + _parsingService = new Mock(); + } - [Fact] - public void ExecuteGoesOkTest() - { - var ast = new Mock(); - ast.Setup(x => x.GetInstructions()) - .Returns(new List { new Halt(0) }); + [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); + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Returns(ast.Object); - var executor = new Executor(_parsingService.Object, _settings.ToOptions()); - Assert.Null(Record.Exception(() => executor.Execute())); - } + var executor = new Executor(_parsingService.Object, _settings.ToOptions()); + Assert.Null(Record.Exception(() => executor.Execute())); + } - [Fact] - public void SemanticExceptionCaughtTest() - { - var ast = new Mock(); - ast.Setup(x => x.GetInstructions()) - .Throws(); + [Fact] + public void SemanticExceptionCaughtTest() + { + var ast = new Mock(); + ast.Setup(x => x.GetInstructions()) + .Throws(); - _parsingService.Setup(x => x.Parse(It.IsAny())) - .Returns(ast.Object); + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Returns(ast.Object); - var executor = new Executor(_parsingService.Object, _settings.ToOptions()); - Assert.Null(Record.Exception(() => executor.Execute())); - } + var executor = new Executor(_parsingService.Object, _settings.ToOptions()); + Assert.Null(Record.Exception(() => executor.Execute())); + } - [Fact] - public void LexerExceptionCaughtTest() - { - _parsingService.Setup(x => x.Parse(It.IsAny())) - .Throws(); + [Fact] + public void LexerExceptionCaughtTest() + { + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Throws(); - var executor = new Executor(_parsingService.Object, _settings.ToOptions()); - Assert.Null(Record.Exception(() => executor.Execute())); - } + var executor = new Executor(_parsingService.Object, _settings.ToOptions()); + Assert.Null(Record.Exception(() => executor.Execute())); + } - [Fact] - public void ParserExceptionCaughtTest() - { - _parsingService.Setup(x => x.Parse(It.IsAny())) - .Throws(); + [Fact] + public void ParserExceptionCaughtTest() + { + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Throws(); - var executor = new Executor(_parsingService.Object, _settings.ToOptions()); - Assert.Null(Record.Exception(() => executor.Execute())); - } + var executor = new Executor(_parsingService.Object, _settings.ToOptions()); + 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(); + [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) }); + 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); + _parsingService.Setup(x => x.Parse(It.IsAny())) + .Returns(ast.Object); - var executor = new Executor(_parsingService.Object, _settings.ToOptions()); - Assert.Null(Record.Exception(() => executor.Execute())); - } + var executor = new Executor(_parsingService.Object, _settings.ToOptions()); + Assert.Null(Record.Exception(() => executor.Execute())); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/Infrastructure/LoggingEntitiesTests.cs b/Interpreter.Tests/Unit/Infrastructure/LoggingEntitiesTests.cs index 554d03cf..53e63e33 100644 --- a/Interpreter.Tests/Unit/Infrastructure/LoggingEntitiesTests.cs +++ b/Interpreter.Tests/Unit/Infrastructure/LoggingEntitiesTests.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; using System.IO.Abstractions; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.FrontEnd.GetTokens; using Interpreter.Lib.FrontEnd.GetTokens.Data; @@ -11,86 +9,85 @@ using Moq; using Xunit; -namespace Interpreter.Tests.Unit.Infrastructure +namespace Interpreter.Tests.Unit.Infrastructure; + +public class LoggingEntitiesTests { - public class LoggingEntitiesTests - { - private readonly Mock _file; - private readonly Mock _fileSystem; + private readonly Mock _file; + private readonly Mock _fileSystem; - public LoggingEntitiesTests() - { - _file = new Mock(); + public LoggingEntitiesTests() + { + _file = new Mock(); - _fileSystem = new Mock(); - _fileSystem.Setup(x => x.File) - .Returns(_file.Object); - } + _fileSystem = new Mock(); + _fileSystem.Setup(x => x.File) + .Returns(_file.Object); + } - [Fact] - public void CorrectFileNameProducedByLexerTest() - { - var lexer = new Mock(); - lexer.Setup(x => x.GetTokens(It.IsAny())) - .Returns(new List()); - lexer.Setup(x => x.ToString()) - .Returns("lexer"); + [Fact] + public void CorrectFileNameProducedByLexerTest() + { + var lexer = new Mock(); + lexer.Setup(x => x.GetTokens(It.IsAny())) + .Returns(new List()); + lexer.Setup(x => x.ToString()) + .Returns("lexer"); - _file.Setup(x => x.WriteAllText( - It.IsAny(), It.IsAny() - )).Verifiable(); + _file.Setup(x => x.WriteAllText( + It.IsAny(), It.IsAny() + )).Verifiable(); - var loggingLexer = new LoggingLexer(lexer.Object, "file", _fileSystem.Object); - loggingLexer.GetTokens(""); + var loggingLexer = new LoggingLexer(lexer.Object, "file", _fileSystem.Object); + loggingLexer.GetTokens(""); - _file.Verify(x => x.WriteAllText( - It.Is(p => p == "file.tokens"), It.Is(c => c == "lexer") - ), Times.Once()); - } + _file.Verify(x => x.WriteAllText( + It.Is(p => p == "file.tokens"), It.Is(c => c == "lexer") + ), Times.Once()); + } - [Fact] - public void CorrectTreeWrittenAndLoggingTreeProducedTest() - { - var ast = new Mock(); - ast.Setup(x => x.ToString()) - .Returns("digraph ast { }"); + [Fact] + public void CorrectTreeWrittenAndLoggingTreeProducedTest() + { + var ast = new Mock(); + ast.Setup(x => x.ToString()) + .Returns("digraph ast { }"); - var parser = new Mock(); - parser.Setup(x => x.TopDownParse(It.IsAny())) - .Returns(ast.Object); + var parser = new Mock(); + parser.Setup(x => x.TopDownParse(It.IsAny())) + .Returns(ast.Object); - _file.Setup(x => x.WriteAllText( - It.IsAny(), It.IsAny() - )).Verifiable(); + _file.Setup(x => x.WriteAllText( + It.IsAny(), It.IsAny() + )).Verifiable(); - var loggingParser = new LoggingParser(parser.Object, "file", _fileSystem.Object); - var parsed = loggingParser.TopDownParse(""); + var loggingParser = new LoggingParser(parser.Object, "file", _fileSystem.Object); + var parsed = loggingParser.TopDownParse(""); - _file.Verify(x => x.WriteAllText( - It.Is(p => p == "ast.dot"), - It.Is(c => c == "digraph ast { }") - ), Times.Once()); - Assert.IsType(parsed); - } + _file.Verify(x => x.WriteAllText( + It.Is(p => p == "ast.dot"), + It.Is(c => c == "digraph ast { }") + ), Times.Once()); + Assert.IsType(parsed); + } - [Fact] - public void CorrectFileNameProducedByTreeTest() - { - var ast = new Mock(); - ast.Setup(x => x.GetInstructions()) - .Returns(new List { new Halt(0) }); + [Fact] + public void CorrectFileNameProducedByTreeTest() + { + var ast = new Mock(); + ast.Setup(x => x.GetInstructions()) + .Returns(new List { new Halt(0) }); - _file.Setup(x => x.WriteAllLines( - It.IsAny(), It.IsAny>() - )).Verifiable(); + _file.Setup(x => x.WriteAllLines( + It.IsAny(), It.IsAny>() + )).Verifiable(); - var loggingTree = new LoggingAbstractSyntaxTree(ast.Object, "file", _fileSystem.Object); - loggingTree.GetInstructions(); + var loggingTree = new LoggingAbstractSyntaxTree(ast.Object, "file", _fileSystem.Object); + loggingTree.GetInstructions(); - _file.Verify(x => x.WriteAllLines( - It.Is(p => p == "file.tac"), - It.Is>(c => c.SequenceEqual(new[] { "0: End" })) - ), Times.Once()); - } + _file.Verify(x => x.WriteAllLines( + It.Is(p => p == "file.tac"), + It.Is>(c => c.SequenceEqual(new[] { "0: End" })) + ), Times.Once()); } } \ No newline at end of file diff --git a/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs b/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs index 37ff1181..d9ee4fd6 100644 --- a/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs +++ b/Interpreter.Tests/Unit/Infrastructure/ParsingServiceTests.cs @@ -5,30 +5,29 @@ using Moq; using Xunit; -namespace Interpreter.Tests.Unit.Infrastructure +namespace Interpreter.Tests.Unit.Infrastructure; + +public class ParsingServiceTests { - public class ParsingServiceTests + [Fact] + public void CertainTextHasBeenParsedTest() { - [Fact] - public void CertainTextHasBeenParsedTest() - { - const string text = "let x = 1 + 2 - 3"; + 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 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 parserProvider = new Mock(); + parserProvider.Setup(x => x.CreateParser()) + .Returns(parser.Object); - var parsingService = new ParsingService(parserProvider.Object); - parsingService.Parse(text); + var parsingService = new ParsingService(parserProvider.Object); + parsingService.Parse(text); - parser.Verify(x => x.TopDownParse( - It.Is(s => s == text) - ), Times.Once()); - } + 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 index 13fde978..1d7a103a 100644 --- a/Interpreter.Tests/Unit/Infrastructure/ProvidersTests.cs +++ b/Interpreter.Tests/Unit/Infrastructure/ProvidersTests.cs @@ -1,5 +1,3 @@ -using System; -using System.Collections.Generic; using Interpreter.Lib.FrontEnd.GetTokens; using Interpreter.Lib.FrontEnd.GetTokens.Data; using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; @@ -11,56 +9,56 @@ using Microsoft.Extensions.Options; using Moq; using Xunit; +using SystemType = System.Type; -namespace Interpreter.Tests.Unit.Infrastructure +namespace Interpreter.Tests.Unit.Infrastructure; + +public class ProvidersTests { - public class ProvidersTests + [Theory] + [InlineData(typeof(Lexer), false)] + [InlineData(typeof(LoggingLexer), true)] + public void CertainLexerProvidedTest(SystemType lexerType, bool dump) { - [Theory] - [InlineData(typeof(Lexer), false)] - [InlineData(typeof(LoggingLexer), true)] - public void CertainLexerProvidedTest(Type lexerType, bool dump) - { - var structureProvider = new Mock(); - structureProvider.Setup(x => x.CreateStructure()) - .Returns(new Structure(new List())); + var structureProvider = new Mock(); + structureProvider.Setup(x => x.CreateStructure()) + .Returns(new Structure(new List())); - var options = new Mock>(); - options.Setup(x => x.Value) - .Returns(new CommandLineSettings - { - Dump = dump, - InputFilePath = "file.js" - }); + var options = new Mock>(); + options.Setup(x => x.Value) + .Returns(new CommandLineSettings + { + Dump = dump, + InputFilePath = "file.js" + }); - var lexerProvider = new LexerProvider(structureProvider.Object, options.Object); - var lexer = lexerProvider.CreateLexer(); + var lexerProvider = new LexerProvider(structureProvider.Object, options.Object); + var lexer = lexerProvider.CreateLexer(); - Assert.IsType(lexerType, lexer); - } + 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" - }); + [Theory] + [InlineData(typeof(Parser), false)] + [InlineData(typeof(LoggingParser), true)] + public void CertainParserProvidedTest(SystemType 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 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(); + var parserProvider = new ParserProvider(lexerProvider.Object, options.Object); + var parser = parserProvider.CreateParser(); - Assert.IsType(parserType, parser); - } + Assert.IsType(parserType, parser); } } \ No newline at end of file diff --git a/Interpreter/CommandLineSettings.cs b/Interpreter/CommandLineSettings.cs index 33a0b842..a56c9ea6 100644 --- a/Interpreter/CommandLineSettings.cs +++ b/Interpreter/CommandLineSettings.cs @@ -1,39 +1,36 @@ -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.IO; using CommandLine; using CommandLine.Text; -namespace Interpreter +namespace Interpreter; + +[SuppressMessage("ReSharper", "UnusedMember.Global")] +[SuppressMessage("ReSharper", "PropertyCanBeMadeInitOnly.Global")] +[ExcludeFromCodeCoverage] +// ReSharper disable once ClassWithVirtualMembersNeverInherited.Global +public class CommandLineSettings { - [SuppressMessage("ReSharper", "UnusedMember.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 virtual string InputFilePath { get; set; } + [Value(0, MetaName = "InputFilePath", Required = true, HelpText = "Path to input file")] + public virtual string InputFilePath { get; set; } - [Option('d', "dump", Default = false, HelpText = "Show dump data of interpreter")] - public virtual bool Dump { get; set; } + [Option('d', "dump", Default = false, HelpText = "Show dump data of interpreter")] + public virtual bool Dump { get; set; } - [Usage(ApplicationAlias = "Interpreter")] - public static IEnumerable Examples + [Usage(ApplicationAlias = "Interpreter")] + public static IEnumerable Examples + { + get { - get - { - yield return new Example("Simple interpretation call", - new CommandLineSettings { InputFilePath = "file.js" }); - yield return new Example("Request dump", - new CommandLineSettings { InputFilePath = "file.js", Dump = true }); - } + yield return new Example("Simple interpretation call", + new CommandLineSettings { InputFilePath = "file.js" }); + yield return new Example("Request dump", + new CommandLineSettings { InputFilePath = "file.js", Dump = true }); } + } - public string GetInputFileName() => - InputFilePath.Split(".js")[0]; + public string GetInputFileName() => + InputFilePath.Split(".js")[0]; - public virtual string GetText() => - File.ReadAllText(InputFilePath); - } + public virtual string GetText() => + File.ReadAllText(InputFilePath); } \ No newline at end of file diff --git a/Interpreter/Interpreter.csproj b/Interpreter/Interpreter.csproj index a199d99a..c6708e46 100644 --- a/Interpreter/Interpreter.csproj +++ b/Interpreter/Interpreter.csproj @@ -2,8 +2,9 @@ Exe - net6.0 - 1.1.5 + net7.0 + 1.2.6 + enable @@ -12,9 +13,9 @@ - - - + + + diff --git a/Interpreter/Program.cs b/Interpreter/Program.cs index 83d5a12a..4c450e67 100644 --- a/Interpreter/Program.cs +++ b/Interpreter/Program.cs @@ -1,5 +1,4 @@ -using System; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using CommandLine; using Microsoft.Extensions.DependencyInjection; using Interpreter.Services.Executor; @@ -12,38 +11,37 @@ using Interpreter.Services.Providers.Impl.StructureProvider; using Microsoft.Extensions.Options; -namespace Interpreter +namespace Interpreter; + +[ExcludeFromCodeCoverage] +public static class Program { - [ExcludeFromCodeCoverage] - public static class Program - { - private static IServiceCollection ServiceCollection { get; } = new ServiceCollection(); - private static IServiceProvider ServiceProvider { get; set; } + private static IServiceCollection ServiceCollection { get; } = new ServiceCollection(); + private static IServiceProvider ServiceProvider { get; set; } - private static void Main(string[] args) => - Parser.Default.ParseArguments(args) - .WithParsed(options => - { - ConfigureServices(options); - ServiceProvider - .GetService()! - .Execute(); - }) - .WithNotParsed(errors => errors.Output()); + private static void Main(string[] args) => + Parser.Default.ParseArguments(args) + .WithParsed(options => + { + ConfigureServices(options); + ServiceProvider + .GetService()! + .Execute(); + }) + .WithNotParsed(errors => errors.Output()); - private static void ConfigureServices(CommandLineSettings settings) - { - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + private static void ConfigureServices(CommandLineSettings settings) + { + ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(); + ServiceCollection.AddSingleton(); - ServiceCollection.AddSingleton(_ => Options.Create(settings)); + ServiceCollection.AddSingleton(_ => Options.Create(settings)); - ServiceProvider = ServiceCollection.BuildServiceProvider(); - } + ServiceProvider = ServiceCollection.BuildServiceProvider(); } } \ No newline at end of file diff --git a/Interpreter/Services/Executor/IExecutor.cs b/Interpreter/Services/Executor/IExecutor.cs index 21ac6b85..f2f22248 100644 --- a/Interpreter/Services/Executor/IExecutor.cs +++ b/Interpreter/Services/Executor/IExecutor.cs @@ -1,7 +1,6 @@ -namespace Interpreter.Services.Executor +namespace Interpreter.Services.Executor; + +public interface IExecutor { - public interface IExecutor - { - void Execute(); - } + void Execute(); } \ No newline at end of file diff --git a/Interpreter/Services/Executor/Impl/Executor.cs b/Interpreter/Services/Executor/Impl/Executor.cs index 53ac4d90..9b12c337 100644 --- a/Interpreter/Services/Executor/Impl/Executor.cs +++ b/Interpreter/Services/Executor/Impl/Executor.cs @@ -1,4 +1,3 @@ -using System; using Interpreter.Lib.BackEnd; using Interpreter.Lib.FrontEnd.GetTokens; using Interpreter.Lib.FrontEnd.TopDownParse; @@ -6,39 +5,38 @@ using Interpreter.Services.Parsing; using Microsoft.Extensions.Options; -namespace Interpreter.Services.Executor.Impl +namespace Interpreter.Services.Executor.Impl; + +public class Executor : IExecutor { - public class Executor : IExecutor + private readonly IParsingService _parsingService; + private readonly CommandLineSettings _commandLineSettings; + + public Executor(IParsingService parsingService, IOptions options) { - private readonly IParsingService _parsingService; - private readonly CommandLineSettings _commandLineSettings; + _parsingService = parsingService; + _commandLineSettings = options.Value; + } - public Executor(IParsingService parsingService, IOptions options) + public void Execute() + { + try { - _parsingService = parsingService; - _commandLineSettings = options.Value; - } + var ast = _parsingService.Parse(_commandLineSettings.GetText()); + var instructions = ast.GetInstructions(); - public void Execute() + var vm = new VirtualMachine(); + vm.Run(instructions); + } + catch (Exception ex) + when (ex is LexerException or ParserException or SemanticException) { - try - { - var ast = _parsingService.Parse(_commandLineSettings.GetText()); - var instructions = ast.GetInstructions(); - - var vm = new VirtualMachine(); - vm.Run(instructions); - } - catch (Exception ex) - when (ex is LexerException or ParserException or SemanticException) - { - Console.WriteLine(ex.Message); - } - catch (Exception ex) - { - Console.WriteLine("Internal Interpreter Error"); - Console.WriteLine(ex); - } + Console.WriteLine(ex.Message); + } + catch (Exception ex) + { + Console.WriteLine("Internal Interpreter Error"); + Console.WriteLine(ex); } } -} +} \ No newline at end of file diff --git a/Interpreter/Services/Parsing/IParsingService.cs b/Interpreter/Services/Parsing/IParsingService.cs index 312e5b70..7b9249e2 100644 --- a/Interpreter/Services/Parsing/IParsingService.cs +++ b/Interpreter/Services/Parsing/IParsingService.cs @@ -1,9 +1,8 @@ using Interpreter.Lib.IR.Ast; -namespace Interpreter.Services.Parsing +namespace Interpreter.Services.Parsing; + +public interface IParsingService { - public interface IParsingService - { - IAbstractSyntaxTree Parse(string text); - } + 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 index 0f105154..2c24a572 100644 --- a/Interpreter/Services/Parsing/Impl/ParsingService.cs +++ b/Interpreter/Services/Parsing/Impl/ParsingService.cs @@ -1,21 +1,20 @@ using Interpreter.Lib.IR.Ast; using Interpreter.Services.Providers; -namespace Interpreter.Services.Parsing.Impl +namespace Interpreter.Services.Parsing.Impl; + +public class ParsingService : IParsingService { - public class ParsingService : IParsingService - { - private readonly IParserProvider _parserProvider; + private readonly IParserProvider _parserProvider; - public ParsingService(IParserProvider parserProvider) - { - _parserProvider = parserProvider; - } + public ParsingService(IParserProvider parserProvider) + { + _parserProvider = parserProvider; + } - public IAbstractSyntaxTree Parse(string text) - { - var parser = _parserProvider.CreateParser(); - return parser.TopDownParse(text); - } + 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 4011e48a..0f34a033 100644 --- a/Interpreter/Services/Providers/ILexerProvider.cs +++ b/Interpreter/Services/Providers/ILexerProvider.cs @@ -1,9 +1,8 @@ using Interpreter.Lib.FrontEnd.GetTokens; -namespace Interpreter.Services.Providers +namespace Interpreter.Services.Providers; + +public interface ILexerProvider { - public interface ILexerProvider - { - ILexer CreateLexer(); - } + ILexer CreateLexer(); } \ No newline at end of file diff --git a/Interpreter/Services/Providers/IParserProvider.cs b/Interpreter/Services/Providers/IParserProvider.cs index 48b188c5..cd7b7101 100644 --- a/Interpreter/Services/Providers/IParserProvider.cs +++ b/Interpreter/Services/Providers/IParserProvider.cs @@ -1,9 +1,8 @@ using Interpreter.Lib.FrontEnd.TopDownParse; -namespace Interpreter.Services.Providers +namespace Interpreter.Services.Providers; + +public interface IParserProvider { - public interface IParserProvider - { - IParser CreateParser(); - } + IParser CreateParser(); } \ No newline at end of file diff --git a/Interpreter/Services/Providers/IStructureProvider.cs b/Interpreter/Services/Providers/IStructureProvider.cs index a45b2a60..037c97e6 100644 --- a/Interpreter/Services/Providers/IStructureProvider.cs +++ b/Interpreter/Services/Providers/IStructureProvider.cs @@ -1,9 +1,8 @@ using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Services.Providers +namespace Interpreter.Services.Providers; + +public interface IStructureProvider { - public interface IStructureProvider - { - Structure CreateStructure(); - } + Structure CreateStructure(); } \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs b/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs index b8fd2578..4ff77b32 100644 --- a/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs +++ b/Interpreter/Services/Providers/Impl/LexerProvider/LexerProvider.cs @@ -3,26 +3,25 @@ using Interpreter.Lib.FrontEnd.GetTokens.Impl; using Microsoft.Extensions.Options; -namespace Interpreter.Services.Providers.Impl.LexerProvider +namespace Interpreter.Services.Providers.Impl.LexerProvider; + +public class LexerProvider : ILexerProvider { - public class LexerProvider : ILexerProvider - { - private readonly IStructureProvider _structureProvider; - private readonly CommandLineSettings _settings; + private readonly IStructureProvider _structureProvider; + private readonly CommandLineSettings _settings; - public LexerProvider(IStructureProvider structureProvider, IOptions options) - { - _structureProvider = structureProvider; - _settings = options.Value; - } + public LexerProvider(IStructureProvider structureProvider, IOptions options) + { + _structureProvider = structureProvider; + _settings = options.Value; + } - public ILexer CreateLexer() - { - var structure = _structureProvider.CreateStructure(); - var lexer = new Lexer(structure); - return _settings.Dump - ? new LoggingLexer(lexer, _settings.GetInputFileName(), new FileSystem()) - : lexer; - } + public ILexer CreateLexer() + { + var structure = _structureProvider.CreateStructure(); + var lexer = new Lexer(structure); + return _settings.Dump + ? new LoggingLexer(lexer, _settings.GetInputFileName(), new FileSystem()) + : 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 index 4b645825..ed297b16 100644 --- a/Interpreter/Services/Providers/Impl/LexerProvider/LoggingLexer.cs +++ b/Interpreter/Services/Providers/Impl/LexerProvider/LoggingLexer.cs @@ -1,35 +1,33 @@ -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO.Abstractions; using Interpreter.Lib.FrontEnd.GetTokens; using Interpreter.Lib.FrontEnd.GetTokens.Data; -namespace Interpreter.Services.Providers.Impl.LexerProvider +namespace Interpreter.Services.Providers.Impl.LexerProvider; + +public class LoggingLexer : ILexer { - public class LoggingLexer : ILexer - { - private readonly ILexer _lexer; - private readonly string _fileName; - private readonly IFileSystem _fileSystem; + private readonly ILexer _lexer; + private readonly string _fileName; + private readonly IFileSystem _fileSystem; - public LoggingLexer(ILexer lexer, string fileName, IFileSystem fileSystem) - { - _lexer = lexer; - _fileName = fileName; - _fileSystem = fileSystem; - } + public LoggingLexer(ILexer lexer, string fileName, IFileSystem fileSystem) + { + _lexer = lexer; + _fileName = fileName; + _fileSystem = fileSystem; + } - [ExcludeFromCodeCoverage] - public Structure Structure => _lexer.Structure; + [ExcludeFromCodeCoverage] + public Structure Structure => _lexer.Structure; - public List GetTokens(string text) - { - var tokens = _lexer.GetTokens(text); - _fileSystem.File.WriteAllText( - $"{_fileName}.tokens", - _lexer.ToString() - ); - return tokens; - } + public List GetTokens(string text) + { + var tokens = _lexer.GetTokens(text); + _fileSystem.File.WriteAllText( + $"{_fileName}.tokens", + _lexer.ToString() + ); + return tokens; } } \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs index cc9d29f1..b8160dbc 100644 --- a/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs +++ b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingAbstractSyntaxTree.cs @@ -1,32 +1,29 @@ -using System.Collections.Generic; using System.IO.Abstractions; -using System.Linq; using Interpreter.Lib.BackEnd.Instructions; using Interpreter.Lib.IR.Ast; -namespace Interpreter.Services.Providers.Impl.ParserProvider +namespace Interpreter.Services.Providers.Impl.ParserProvider; + +public class LoggingAbstractSyntaxTree : IAbstractSyntaxTree { - public class LoggingAbstractSyntaxTree : IAbstractSyntaxTree - { - private readonly IAbstractSyntaxTree _ast; - private readonly string _fileName; - private readonly IFileSystem _fileSystem; + private readonly IAbstractSyntaxTree _ast; + private readonly string _fileName; + private readonly IFileSystem _fileSystem; - public LoggingAbstractSyntaxTree(IAbstractSyntaxTree ast, string fileName, IFileSystem fileSystem) - { - _ast = ast; - _fileName = fileName; - _fileSystem = fileSystem; - } + public LoggingAbstractSyntaxTree(IAbstractSyntaxTree ast, string fileName, IFileSystem fileSystem) + { + _ast = ast; + _fileName = fileName; + _fileSystem = fileSystem; + } - public List GetInstructions() - { - var instructions = _ast.GetInstructions(); - _fileSystem.File.WriteAllLines( - $"{_fileName}.tac", - instructions.OrderBy(i => i).Select(i => i.ToString()) - ); - return instructions; - } + public List GetInstructions() + { + var instructions = _ast.GetInstructions(); + _fileSystem.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 index a91cc31b..3fd04d97 100644 --- a/Interpreter/Services/Providers/Impl/ParserProvider/LoggingParser.cs +++ b/Interpreter/Services/Providers/Impl/ParserProvider/LoggingParser.cs @@ -2,27 +2,26 @@ using Interpreter.Lib.FrontEnd.TopDownParse; using Interpreter.Lib.IR.Ast; -namespace Interpreter.Services.Providers.Impl.ParserProvider +namespace Interpreter.Services.Providers.Impl.ParserProvider; + +public class LoggingParser : IParser { - public class LoggingParser : IParser - { - private readonly IParser _parser; - private readonly string _fileName; - private readonly IFileSystem _fileSystem; + private readonly IParser _parser; + private readonly string _fileName; + private readonly IFileSystem _fileSystem; - public LoggingParser(IParser parser, string fileName, IFileSystem fileSystem) - { - _parser = parser; - _fileName = fileName; - _fileSystem = fileSystem; - } + public LoggingParser(IParser parser, string fileName, IFileSystem fileSystem) + { + _parser = parser; + _fileName = fileName; + _fileSystem = fileSystem; + } - public IAbstractSyntaxTree TopDownParse(string text) - { - var ast = _parser.TopDownParse(text); - var astDot = ast.ToString(); - _fileSystem.File.WriteAllText("ast.dot", astDot); - return new LoggingAbstractSyntaxTree(ast, _fileName, _fileSystem); - } + public IAbstractSyntaxTree TopDownParse(string text) + { + var ast = _parser.TopDownParse(text); + var astDot = ast.ToString(); + _fileSystem.File.WriteAllText("ast.dot", astDot); + return new LoggingAbstractSyntaxTree(ast, _fileName, _fileSystem); } } \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs b/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs index d2cbd2c4..25b5b3a2 100644 --- a/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs +++ b/Interpreter/Services/Providers/Impl/ParserProvider/ParserProvider.cs @@ -3,26 +3,25 @@ using Parser = Interpreter.Lib.FrontEnd.TopDownParse.Impl.Parser; using Microsoft.Extensions.Options; -namespace Interpreter.Services.Providers.Impl.ParserProvider +namespace Interpreter.Services.Providers.Impl.ParserProvider; + +public class ParserProvider : IParserProvider { - public class ParserProvider : IParserProvider - { - private readonly ILexerProvider _lexerProvider; - private readonly CommandLineSettings _settings; + private readonly ILexerProvider _lexerProvider; + private readonly CommandLineSettings _settings; - public ParserProvider(ILexerProvider lexerProvider, IOptions options) - { - _lexerProvider = lexerProvider; - _settings = options.Value; - } + 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(), new FileSystem()) - : parser; - } + public IParser CreateParser() + { + var lexer = _lexerProvider.CreateLexer(); + var parser = new Parser(lexer); + return _settings.Dump + ? new LoggingParser(parser, _settings.GetInputFileName(), new FileSystem()) + : parser; } } \ No newline at end of file diff --git a/Interpreter/Services/Providers/Impl/StructureProvider/StructureProvider.cs b/Interpreter/Services/Providers/Impl/StructureProvider/StructureProvider.cs index 83c06c78..90f5e186 100644 --- a/Interpreter/Services/Providers/Impl/StructureProvider/StructureProvider.cs +++ b/Interpreter/Services/Providers/Impl/StructureProvider/StructureProvider.cs @@ -1,49 +1,46 @@ -using System; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; using Interpreter.Lib.FrontEnd.GetTokens.Data; using Interpreter.Lib.FrontEnd.GetTokens.Data.TokenTypes; -namespace Interpreter.Services.Providers.Impl.StructureProvider -{ - public class StructureProvider : IStructureProvider - { - public Structure CreateStructure() => - JsonSerializer.Deserialize( - TokenTypes.Json, - new JsonSerializerOptions - { - Converters = { new StructureReadConverter() } - }); +namespace Interpreter.Services.Providers.Impl.StructureProvider; - [ExcludeFromCodeCoverage] - private class StructureReadConverter : JsonConverter - { - public override Structure Read(ref Utf8JsonReader reader, - Type typeToConvert, JsonSerializerOptions options) +public class StructureProvider : IStructureProvider +{ + public Structure CreateStructure() => + JsonSerializer.Deserialize( + TokenTypes.Json, + new JsonSerializerOptions { - using var jsonDocument = JsonDocument.ParseValue(ref reader); - var tokenTypes = jsonDocument.RootElement - .EnumerateArray().Select(element => - { - var tag = element.GetProperty("tag").GetString(); - var pattern = element.GetProperty("pattern").GetString(); - var priority = element.GetProperty("priority").GetInt32(); + Converters = { new StructureReadConverter() } + }); - var ignorable = element.TryGetProperty("canIgnore", out var canIgnore); + [ExcludeFromCodeCoverage] + private class StructureReadConverter : JsonConverter + { + public override Structure Read(ref Utf8JsonReader reader, + Type typeToConvert, JsonSerializerOptions options) + { + using var jsonDocument = JsonDocument.ParseValue(ref reader); + var tokenTypes = jsonDocument.RootElement + .EnumerateArray().Select(element => + { + var tag = element.GetProperty("tag").GetString(); + var pattern = element.GetProperty("pattern").GetString(); + var priority = element.GetProperty("priority").GetInt32(); - return ignorable && canIgnore.GetBoolean() - ? new IgnorableType(tag, pattern, priority) - : new TokenType(tag, pattern, priority); - }).ToList(); - return new Structure(tokenTypes); - } + var ignorable = element.TryGetProperty("canIgnore", out var canIgnore); - public override void Write(Utf8JsonWriter writer, - Structure value, JsonSerializerOptions options) => - throw new NotImplementedException(); + return ignorable && canIgnore.GetBoolean() + ? new IgnorableType(tag, pattern, priority) + : new TokenType(tag, pattern, priority); + }).ToList(); + return new Structure(tokenTypes); } + + public override void Write(Utf8JsonWriter writer, + Structure value, JsonSerializerOptions options) => + throw new NotImplementedException(); } } \ No newline at end of file diff --git a/Interpreter/TokenTypes.cs b/Interpreter/TokenTypes.cs index 0f6d2ac0..f604bdba 100644 --- a/Interpreter/TokenTypes.cs +++ b/Interpreter/TokenTypes.cs @@ -1,119 +1,121 @@ -namespace Interpreter +namespace Interpreter; + +public static class TokenTypes { - public static class TokenTypes - { - public const string Json = @"[ - { - ""tag"": ""Comment"", - ""pattern"": ""[\/]{2}.*"", - ""priority"": 0, - ""canIgnore"": true - }, - { - ""tag"": ""Ident"", - ""pattern"": ""[a-zA-Z][a-zA-Z0-9]*"", - ""priority"": 50 - }, - { - ""tag"": ""IntegerLiteral"", - ""pattern"": ""[0-9]+"", - ""priority"": 3 - }, - { - ""tag"": ""FloatLiteral"", - ""pattern"": ""[0-9]+[.][0-9]+"", - ""priority"": 2 - }, - { - ""tag"": ""NullLiteral"", - ""pattern"": ""null"", - ""priority"": 4 - }, - { - ""tag"": ""BooleanLiteral"", - ""pattern"": ""true|false"", - ""priority"": 5 - }, - { - ""tag"": ""StringLiteral"", - ""pattern"": ""\\\""(\\\\.|[^\""\\\\])*\\\"""", - ""priority"": 6 - }, - { - ""tag"": ""Keyword"", - ""pattern"": ""let|const|function|if|else|while|break|continue|return|as|type"", - ""priority"": 11 - }, - { - ""tag"": ""Operator"", - ""pattern"": ""[+]{1,2}|[-]|[*]|[\/]|[%]|([!]|[=])[=]|([<]|[>])[=]?|[!]|[|]{2}|[&]{2}|[~]|[:]{2}"", - ""priority"": 12 - }, - { - ""tag"": ""Arrow"", - ""pattern"": ""[=][>]"", - ""priority"": 13 - }, - { - ""tag"": ""Comma"", - ""pattern"": ""[,]"", - ""priority"": 100 - }, - { - ""tag"": ""Dot"", - ""pattern"": ""[.]"", - ""priority"": 105 - }, - { - ""tag"": ""LeftCurl"", - ""pattern"": ""[{]"", - ""priority"": 101 - }, - { - ""tag"": ""RightCurl"", - ""pattern"": ""[}]"", - ""priority"": 102 - }, - { - ""tag"": ""LeftParen"", - ""pattern"": ""[(]"", - ""priority"": 103 - }, - { - ""tag"": ""RightParen"", - ""pattern"": ""[)]"", - ""priority"": 104 - }, - { - ""tag"": ""LeftBracket"", - ""pattern"": ""[[]"", - ""priority"": 107 - }, - { - ""tag"": ""RightBracket"", - ""pattern"": ""[]]"", - ""priority"": 109 - }, - { - ""tag"": ""Assign"", - ""pattern"": ""[=]"", - ""priority"": 99 - }, - { - ""tag"": ""QuestionMark"", - ""pattern"": ""[?]"", - ""priority"": 90 - }, - { - ""tag"": ""Colon"", - ""pattern"": ""[:]"", - ""priority"": 91 - }, - { - ""tag"": ""SemiColon"", - ""pattern"": ""[;]"", - ""priority"": 92 - } - ]"; - } + public const string Json = + """ + [ + { + "tag": "Comment", + "pattern": "[\/]{2}.*", + "priority": 0, + "canIgnore": true + }, + { + "tag": "Ident", + "pattern": "[a-zA-Z][a-zA-Z0-9]*", + "priority": 50 + }, + { + "tag": "IntegerLiteral", + "pattern": "[0-9]+", + "priority": 3 + }, + { + "tag": "FloatLiteral", + "pattern": "[0-9]+[.][0-9]+", + "priority": 2 + }, + { + "tag": "NullLiteral", + "pattern": "null", + "priority": 4 + }, + { + "tag": "BooleanLiteral", + "pattern": "true|false", + "priority": 5 + }, + { + "tag": "StringLiteral", + "pattern": "\\\"(\\\\.|[^\"\\\\])*\\\"", + "priority": 6 + }, + { + "tag": "Keyword", + "pattern": "let|const|function|if|else|while|break|continue|return|as|type", + "priority": 11 + }, + { + "tag": "Operator", + "pattern": "[+]{1,2}|[-]|[*]|[\/]|[%]|([!]|[=])[=]|([<]|[>])[=]?|[!]|[|]{2}|[&]{2}|[~]|[:]{2}", + "priority": 12 + }, + { + "tag": "Arrow", + "pattern": "[=][>]", + "priority": 13 + }, + { + "tag": "Comma", + "pattern": "[,]", + "priority": 100 + }, + { + "tag": "Dot", + "pattern": "[.]", + "priority": 105 + }, + { + "tag": "LeftCurl", + "pattern": "[{]", + "priority": 101 + }, + { + "tag": "RightCurl", + "pattern": "[}]", + "priority": 102 + }, + { + "tag": "LeftParen", + "pattern": "[(]", + "priority": 103 + }, + { + "tag": "RightParen", + "pattern": "[)]", + "priority": 104 + }, + { + "tag": "LeftBracket", + "pattern": "[[]", + "priority": 107 + }, + { + "tag": "RightBracket", + "pattern": "[]]", + "priority": 109 + }, + { + "tag": "Assign", + "pattern": "[=]", + "priority": 99 + }, + { + "tag": "QuestionMark", + "pattern": "[?]", + "priority": 90 + }, + { + "tag": "Colon", + "pattern": "[:]", + "priority": 91 + }, + { + "tag": "SemiColon", + "pattern": "[;]", + "priority": 92 + } + ] + """; } \ No newline at end of file diff --git a/Readme.md b/Readme.md index acdfd1d6..de8ec1ab 100644 --- a/Readme.md +++ b/Readme.md @@ -1,10 +1,10 @@ -![Code Coverage](https://img.shields.io/badge/Code%20Coverage-42%25-critical?style=flat) +![Code Coverage](https://img.shields.io/badge/Code%20Coverage-43%25-critical?style=flat) Package | Line Rate | Health -------- | --------- | ------ Interpreter.Lib | 40% | ❌ Interpreter | 100% | ✔ -**Summary** | **42%** (925 / 2173) | ❌ +**Summary** | **43%** (925 / 2173) | ❌ _Minimum allowed line rate is `80%`_ @@ -161,7 +161,7 @@ let s = v2d as string ### Требования -- .NET 6 SDK +- .NET 7 SDK ### Сборка После клонирования репозитория идём в папку проекта `Interpreter`. @@ -174,7 +174,7 @@ let s = v2d as string ### Запуск ``` -Interpreter 1.1.5 +Interpreter 1.2.6 Copyright (C) 2022 Interpreter USAGE: Simple interpretation call: