|
0 |
using System;
|
|
1 |
using System.Collections.Generic;
|
|
2 |
using System.Linq;
|
|
3 |
using System.Text;
|
|
4 |
using System.Threading.Tasks;
|
|
5 |
|
|
6 |
namespace Tau
|
|
7 |
{
|
|
8 |
class Op
|
|
9 |
{
|
|
10 |
public delegate void Visitor(Stack<Double> s);
|
|
11 |
public string Name;
|
|
12 |
public Visitor Func;
|
|
13 |
public string Doc;
|
|
14 |
|
|
15 |
public Op(string n, string d, Visitor f)
|
|
16 |
{
|
|
17 |
Name = n;
|
|
18 |
Func = f;
|
|
19 |
Doc = d;
|
|
20 |
}
|
|
21 |
}
|
|
22 |
|
|
23 |
public class StackMachine
|
|
24 |
{
|
|
25 |
private Stack<Double> values;
|
|
26 |
private Dictionary<string, Op> ops;
|
|
27 |
|
|
28 |
protected StackMachine()
|
|
29 |
{
|
|
30 |
values = new Stack<double>();
|
|
31 |
ops = new Dictionary<string, Op>();
|
|
32 |
}
|
|
33 |
|
|
34 |
void AddOp(Op o)
|
|
35 |
{
|
|
36 |
ops.Add(o.Name, o);
|
|
37 |
}
|
|
38 |
|
|
39 |
private delegate double Binary(double v1, double v2);
|
|
40 |
private static Op.Visitor BinOp(Binary func)
|
|
41 |
{
|
|
42 |
return (Stack<Double> values) =>
|
|
43 |
{
|
|
44 |
if (values.Count == 0)
|
|
45 |
return;
|
|
46 |
double v1 = values.Pop();
|
|
47 |
double v2 = values.Count == 0 ? v1 : values.Pop();
|
|
48 |
values.Push(func(v1, v2));
|
|
49 |
};
|
|
50 |
}
|
|
51 |
|
|
52 |
public static StackMachine New()
|
|
53 |
{
|
|
54 |
StackMachine sm = new StackMachine();
|
|
55 |
sm.AddOp(new Op("+", "adds the top two values", BinOp((v1, v2) => { return v2 + v1; })));
|
|
56 |
sm.AddOp(new Op("*", "multiplies the top two values", BinOp((v1, v2) => { return v2 * v1; })));
|
|
57 |
sm.AddOp(new Op("-", "subtracts the top value from the value below it", BinOp((v1, v2) => { return v2 - v1; })));
|
|
58 |
sm.AddOp(new Op("/", "divides the top value into the value below it", BinOp((v1, v2) => { return v2 - v1; })));
|
|
59 |
sm.AddOp(new Op("dup", "duplicates the top value on the stack", (Stack<Double> values) => {
|
|
60 |
if (values.Count == 0)
|
|
61 |
return;
|
|
62 |
double v = values.Pop();
|
|
63 |
values.Push(v);
|
|
64 |
values.Push(v);
|
|
65 |
}));
|
|
66 |
sm.AddOp(new Op("swap", "swaps the top two values on the stack", (Stack<Double> values) => {
|
|
67 |
if (values.Count < 2)
|
|
68 |
return;
|
|
69 |
double v1 = values.Pop();
|
|
70 |
double v2 = values.Pop();
|
|
71 |
values.Push(v1);
|
|
72 |
values.Push(v2);
|
|
73 |
}));
|
|
74 |
return sm;
|
|
75 |
}
|
|
76 |
|
|
77 |
public void Run(string data)
|
|
78 |
{
|
|
79 |
string[] bits = data.Split();
|
|
80 |
foreach (string b in bits)
|
|
81 |
{
|
|
82 |
double res;
|
|
83 |
if (Double.TryParse(b, out res))
|
|
84 |
{
|
|
85 |
Push(res);
|
|
86 |
continue;
|
|
87 |
}
|
|
88 |
Push(b);
|
|
89 |
}
|
|
90 |
}
|
|
91 |
|
|
92 |
|
|
93 |
public void Push(string opname)
|
|
94 |
{
|
|
95 |
Op op;
|
|
96 |
if (ops.TryGetValue(opname, out op))
|
|
97 |
{
|
|
98 |
op.Func(values);
|
|
99 |
}
|
|
100 |
}
|
|
101 |
|
|
102 |
public void Push(Double v)
|
|
103 |
{
|
|
104 |
values.Push(v);
|
|
105 |
}
|
|
106 |
|
|
107 |
public string State()
|
|
108 |
{
|
|
109 |
List<Double> st = values.ToList();
|
|
110 |
st.Reverse();
|
|
111 |
StringBuilder res = new StringBuilder();
|
|
112 |
foreach (double s in st)
|
|
113 |
{
|
|
114 |
res.Append(s);
|
|
115 |
res.Append("\n");
|
|
116 |
}
|
|
117 |
return res.ToString();
|
|
118 |
}
|
|
119 |
}
|
|
120 |
}
|