-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathruntime.cpp
More file actions
220 lines (184 loc) · 6.49 KB
/
runtime.cpp
File metadata and controls
220 lines (184 loc) · 6.49 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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
//
// Created by cre-chan on 19-12-24.
//
#include "stdafx.h"
#include "syntax.h"
#include "SymbolTable.hpp"
#include "symantics.h"
#include "codegen.h"
#include "runtime.h"
//在求值栈里使用的项
using ValTerm=variant<Function, int, bool>;
using NumOfTerms=int;
void skip_expr(CodeText &code) {
int count = 0;//括号的差
do {
if (code.front().index() == 0 && get<Operator>(code.front()).opcode == Operator::lbr)
count++;
if (code.front().index() == 0 && get<Operator>(code.front()).opcode == Operator::rbr)
count--;
code.increment();
} while (count != 0);
}
variant<Function, int, bool> evaluate(const shared_ptr<SymbolTableRT> &env, CodeText &code) {
auto &head = code.front();
//将程序中的项转换成值
auto term_to_rt_term = [&env](const variant<monostate, bool, int, variable_name> &term) -> ValTerm {
switch (term.index()) {
case 1:
return get<1>(term);
case 2:
return get<2>(term);
case 3:
return *env->find(get<3>(term));
}
};
//如果是项的话
if (head.index() == 1) {
auto &term = get<1>(head);
code.increment();
return term_to_rt_term(term.val);
} else {
vector<ValTerm> ops;
code.increment();
//取出所有运算数直到遇到运算符,每次循环开始时ind都是下一个term在的位置
//此处的move是为了过类型检查,并不会有内存上的影响
auto myenv=env;
do {
//尝试对各项进行求值,若抛出异常,则更新求值环境
try {
ops.push_back(evaluate(myenv, code));
}catch(shared_ptr<SymbolTableRT>& tbl){
myenv=tbl;
}
} while (code.front().index() == 1 || get<Operator>(code.front()).opcode == Operator::lbr);
//先执行计算,因为在左括号之后不可能紧跟一个运算符,因此进行计算是安全的
//获得运算符并将pc指向运算符下一个符号,视情况有可能需要再次跳跃
auto &op = get<Operator>(code.front());
code.increment();
// code.increment();
switch (op.opcode) {
case Operator::plus: {
int cur = get<int>(ops.front());
for (int i = 1; i < ops.size(); i++)
cur += get<int>(ops[i]);
code.increment();
return cur;
}
case Operator::minus: {
int cur = get<int>(ops.front());
for (int i = 1; i < ops.size(); i++)
cur -= get<int>(ops[i]);
code.increment();
return cur;
}
case Operator::mult: {
int cur = get<int>(ops.front());
for (int i = 1; i < ops.size(); i++)
cur *= get<int>(ops[i]);
code.increment();
return cur;
}
case Operator::div: {
int cur = get<int>(ops.front());
for (int i = 1; i < ops.size(); i++)
cur /= get<int>(ops[i]);
//跳过右括号
code.increment();
return cur;
}
case Operator::lbr:
throw exception();
// 此分支不可能,lbr
case Operator::rbr: {
//从队尾移出apply的函数
Function func = get<Function>(move(ops.back()));
ops.pop_back();
auto subenv = env;
for (int i = 0; i < func.arglist.size(); i++) {
subenv = subenv->insert(func.arglist[i], make_shared<ValTerm>(ops[i]));
}
auto exec_proc = CodeText{func.executable};
return evaluate(subenv, exec_proc);
}
case Operator::branch: {
bool cond = get<bool>(ops.front());
if (!cond) {
skip_expr(code);
auto ret = evaluate(env, code);
code.increment();
return ret;
} else {
auto ret = evaluate(env, code);
skip_expr(code);
code.increment();
return ret;
}
}
case Operator::lt: {
int expr1, expr2;
expr1 = get<int>(ops[0]);
expr2 = get<int>(ops[1]);
code.increment();
return expr1 < expr2;
}
case Operator::le: {
int expr1, expr2;
expr1 = get<int>(ops[0]);
expr2 = get<int>(ops[1]);
code.increment();
return expr1 <= expr2;
}
case Operator::gt: {
int expr1, expr2;
expr1 = get<int>(ops[0]);
expr2 = get<int>(ops[1]);
code.increment();
return expr1 > expr2;
}
case Operator::ge: {
int expr1, expr2;
expr1 = get<int>(ops[0]);
expr2 = get<int>(ops[1]);
code.increment();
return expr1 >= expr2;
}
case Operator::eq: {
int expr1, expr2;
expr1 = get<int>(ops[0]);
expr2 = get<int>(ops[1]);
code.increment();
return expr1 == expr2;
}
case Operator::bind: {
//跳过下一个括号并抛出修改过的上下文
code.increment();
throw env->insert(op.name, make_shared<ValTerm>(ops.front()));
}
case Operator::identity:
code.increment();
return ops.front();
// 此分支被删除
}
}
}
shared_ptr<SymbolTableRT> sig_to_runtime(FuncDefsLow defs) {
auto ret = SymbolTableRT::NIL();
for (auto &[name, sig]:defs) {
auto &[args,exec]=sig;
vector<string> arglist;
for (auto arg:args)
arglist.push_back(move(arg));
//往ret里插入函数定义
ret = ret->insert(name, make_shared<ValTerm>(Function{move(arglist), move(exec)}));
}
return ret;
}
CodeText::CodeText(const Commands &temp) : pos(temp.cbegin()) {
}
const Term &CodeText::front() {
return *(pos);
}
void CodeText::increment() {
pos++;
}