/
VirtualMachine.cs
74 lines (60 loc) · 1.82 KB
/
VirtualMachine.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
using Interpreter.Lib.BackEnd.Instructions;
namespace Interpreter.Lib.BackEnd;
public record VirtualMachine(
Stack<Call> CallStack, Stack<Frame> Frames,
Stack<(string Id, object Value)> Arguments,
TextWriter Writer
)
{
public VirtualMachine() :
this(new(), new(), new(), Console.Out) { }
public void Run(List<Instruction> instructions)
{
Frames.Push(new Frame());
var address = 0;
while (!instructions[address].End())
{
var instruction = instructions[address];
var jump = instruction.Execute(this);
address = jump;
}
instructions[address].Execute(this);
}
}
public record Call(
int From, FunctionInfo To,
List<(string Id, object Value)> Parameters,
string Where = null)
{
public override string ToString() =>
$"{From} => {To.Location}: {To.Id}({string.Join(", ", Parameters.Select(x => $"{x.Id}: {x.Value}"))})";
}
public record FunctionInfo(string Id, int Location = 0, string MethodOf = null)
{
public int Location { get; set; } = Location;
public string MethodOf { get; set; } = MethodOf;
public string CallId() =>
MethodOf == null
? Id
: $"{MethodOf}.{Id}";
public override string ToString() =>
$"({Location}, {CallId()})";
}
public class Frame
{
private readonly Dictionary<string, object> _variables = new();
private readonly Frame _parentFrame;
public int ReturnAddress { get; }
public Frame(int returnAddress = 0, Frame parentFrame = null)
{
ReturnAddress = returnAddress;
_parentFrame = parentFrame;
}
public object this[string id]
{
get => _variables.ContainsKey(id)
? _variables[id]
: _parentFrame?[id];
set => _variables[id] = value;
}
}