-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStackMachine.cs
More file actions
144 lines (130 loc) · 4.39 KB
/
StackMachine.cs
File metadata and controls
144 lines (130 loc) · 4.39 KB
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
using System;
using System.Collections.Generic;
using Liu233w.StackMachine.Exceptions;
using Liu233w.StackMachine.Instructions;
namespace Liu233w.StackMachine
{
/// <summary>
/// 栈帧虚拟机,用于运行 <see cref="StackFrameFunction"/>
/// </summary>
public class StackMachine
{
private Stack<StackFrameFunction> _callingStack = new Stack<StackFrameFunction>();
/// <summary>
/// 在虚拟机上运行函数,并返回结果。此操作将清空当前的调用栈。
/// </summary>
/// <param name="func"></param>
/// <returns></returns>
public object Run(StackFrameFunction func)
{
_callingStack.Clear();
_callingStack.Push(func);
StartStepping();
return ((StackFrameResult)_callingStack.Pop()).Result;
}
/// <summary>
/// 在当前的虚拟机上运行 Continuation
/// </summary>
/// <param name="continuation"></param>
/// <param name="input"></param>
/// <returns></returns>
public object RunWithContinuation(Continuation continuation, object input)
{
ResumeWithContinuation(continuation, input);
StartStepping();
return ((StackFrameResult)_callingStack.Pop()).Result;
}
/// <summary>
/// 恢复当前续延
/// </summary>
/// <param name="cont">要恢复的续延</param>
/// <param name="result">续延的返回值</param>
private void ResumeWithContinuation(Continuation cont, object result)
{
_callingStack = cont.GetCallingStack();
ResumeWithResult(result);
}
/// <summary>
/// 运行虚拟机,直到调用栈的顶部是结果为止
/// </summary>
private void StartStepping()
{
while (_callingStack.Count > 1 || !(_callingStack.Peek() is StackFrameResult))
{
object result = null;
if (_callingStack.Peek() is StackFrameResult resultFrame)
{
_callingStack.Pop();
result = resultFrame.Result;
}
var instruction = _callingStack.Peek().StepMove(result);
ExecInstruction(instruction);
}
}
private void ExecInstruction(FuncInstructionBase instruction)
{
switch (instruction)
{
case NoneInstruction _:
{
// Nothing here
break;
}
case ReturnInstruction ret:
{
HandleFunctionReturn(ret.Result);
break;
}
case CallFuncInstruction call:
{
PushStack(call.Func);
break;
}
case CallCcInstruction callcc:
{
HandleCallCc(callcc.Lambda);
break;
}
case ResumeContinuationInstruction resumeContinuation:
{
ResumeWithContinuation(resumeContinuation.Cont, resumeContinuation.Input);
break;
}
default:
{
throw new InvalidInstructionException("不支持此指令");
}
}
}
private void PushStack(StackFrameFunction func)
{
_callingStack.Push(func);
}
/// <summary>
/// 处理 CallCc 操作
/// </summary>
/// <returns></returns>
private void HandleCallCc(Func<Continuation, object> lambda)
{
var result = lambda(new Continuation(_callingStack));
ResumeWithResult(result);
}
/// <summary>
/// 用一个结果栈帧来代替栈顶的函数栈帧
/// </summary>
/// <param name="result"></param>
private void HandleFunctionReturn(object result)
{
_callingStack.Pop();
ResumeWithResult(result);
}
/// <summary>
/// 在栈顶放入一个结果栈帧
/// </summary>
/// <param name="result"></param>
private void ResumeWithResult(object result)
{
_callingStack.Push(new StackFrameResult(result));
}
}
}