-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Новая система адресации инструкций (#21)
* initial of the branch * контракт адреса * Переезд на .NET 7 (#24) * обновление sdk в проекте * обновление sdk в ci * переход на json raw string literal * обновление nuget пакетов * Генерация отчёта о покрытии на уровне конфигурации проекта coverlet-coverage/coverlet#1391 * Генерация отчёта о покрытии на уровне конфигурации проекта coverlet-coverage/coverlet#1391 * versioning * Update Readme.md * draft алгоритма работы коллекции * Использование последних наворотов шарпа (#26) * versioning * enabling implicit usings (#25) * local scoped namespaces (#27) * after merge * разработка алгоритма вставки в коллекцию * пакетная вставка * доработка алгоритма вставки * индексатор * прямая итерация над коллекцией * важная доработка вставки - сгенерированный адрес проставляется инструкции, больше не требуется создавать адрес для создания инструкции * переименовал сущность адреса * доработка массовой вставки * алгоритм удаления инструкции * unit tests * more tests
- Loading branch information
Showing
159 changed files
with
4,767 additions
and
4,845 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<Instruction> | ||
{ | ||
private readonly LinkedList<IAddress> _addresses = new(); | ||
private readonly Dictionary<IAddress, LinkedListNode<IAddress>> _addressToNode = new(); | ||
private readonly Dictionary<LinkedListNode<IAddress>, 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<Instruction> 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<Instruction> GetEnumerator() => | ||
_addresses.Select(address => this[address]) | ||
.GetEnumerator(); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => | ||
GetEnumerator(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()}}}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Interpreter.Lib.BackEnd.Addresses; | ||
|
||
public interface IAddress : IEquatable<IAddress> | ||
{ | ||
IAddress Next { get; set; } | ||
|
||
int GetHashCode(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<double> | ||
{ | ||
public override double Read(ref Utf8JsonReader reader, | ||
Type typeToConvert, JsonSerializerOptions options) => | ||
throw new NotImplementedException(); | ||
[ExcludeFromCodeCoverage] | ||
private class DoubleValueWriteConverter : JsonConverter<double> | ||
{ | ||
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); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()}"; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string, object>) frame[_function.MethodOf]; | ||
foreach (var (key, value) in obj) | ||
{ | ||
var obj = (Dictionary<string, object>) 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}"; | ||
} |
Oops, something went wrong.