Skip to content

Новая система адресации инструкций #21

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 20 commits into from
Dec 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b36b832
initial of the branch
Stepami Oct 17, 2022
e3e0c92
контракт адреса
Stepami Nov 16, 2022
5742d5e
Переезд на .NET 7 (#24)
Stepami Dec 10, 2022
6cfd18f
Update Readme.md
Stepami Dec 10, 2022
1e1ed77
Merge branch 'master' into feature/new-instructions-adress-system
Stepami Dec 10, 2022
49f0070
draft алгоритма работы коллекции
Stepami Dec 12, 2022
fde29b3
Использование последних наворотов шарпа (#26)
Stepami Dec 12, 2022
6431f01
Merge branch 'master' into feature/new-instructions-adress-system
Stepami Dec 12, 2022
93b728c
after merge
Stepami Dec 12, 2022
bb78a92
разработка алгоритма вставки в коллекцию
Stepami Dec 19, 2022
4586214
пакетная вставка
Stepami Dec 19, 2022
7984835
доработка алгоритма вставки
Stepami Dec 19, 2022
fb18105
индексатор
Stepami Dec 19, 2022
6b69a6b
прямая итерация над коллекцией
Stepami Dec 19, 2022
45934cb
важная доработка вставки - сгенерированный адрес проставляется инстру…
Stepami Dec 19, 2022
ed65da9
переименовал сущность адреса
Stepami Dec 19, 2022
ea96ab8
доработка массовой вставки
Stepami Dec 23, 2022
7d1bae2
алгоритм удаления инструкции
Stepami Dec 23, 2022
5d7adcf
unit tests
Stepami Dec 23, 2022
e315b42
more tests
Stepami Dec 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
69 changes: 69 additions & 0 deletions Interpreter.Lib/BackEnd/AddressedInstructions.cs
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();
}
31 changes: 31 additions & 0 deletions Interpreter.Lib/BackEnd/Addresses/HashedAddress.cs
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()}}}";
}
8 changes: 8 additions & 0 deletions Interpreter.Lib/BackEnd/Addresses/IAddress.cs
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();
}
24 changes: 24 additions & 0 deletions Interpreter.Lib/BackEnd/Addresses/Label.cs
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;
}
77 changes: 38 additions & 39 deletions Interpreter.Lib/BackEnd/Instructions/AsString.cs
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);
}
}
}
21 changes: 10 additions & 11 deletions Interpreter.Lib/BackEnd/Instructions/BeginFunction.cs
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()}";
}
72 changes: 34 additions & 38 deletions Interpreter.Lib/BackEnd/Instructions/CallFunction.cs
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}";
}
Loading