-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpair.cpp
71 lines (56 loc) · 1.62 KB
/
pair.cpp
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
#include "pair.h"
using namespace stran;
sp<datum> stran::next(sp<datum> &args) {
assert(args && "not enough args");
const sp<pair> curr_pair(sp_cast<pair>(args));
assert(curr_pair && "improper expression list");
args = curr_pair->cdr;
return curr_pair->car;
}
pair::operator std::string() const {
std::string result("(" + to_string(car));
sp<datum> p_tail(cdr);
for (sp<pair> curr_pair(sp_cast<pair>(p_tail)); curr_pair;) {
p_tail = curr_pair->cdr;
result += " " + to_string(curr_pair->car);
curr_pair = sp_cast<pair>(p_tail);
}
if (p_tail) {
result += " . " + to_string(p_tail);
}
return result + ")";
}
sp<datum> closure::call(sp<datum> args, const sp<env> &curr_env) const {
const sp<env> eval_env(make_sp<env>(context));
const auto eval_body([&]() -> sp<datum> {
sp<datum> result;
sp<pair> exprs(body);
while (exprs) {
result = eval(exprs->car, eval_env);
exprs = sp_cast<pair>(exprs->cdr);
}
return result;
});
for (size_t i(0); i + 1 < formals.size(); ++i) {
eval_env->define(formals[i], eval_next(args, curr_env));
}
if (!variadic) {
if (!formals.empty()) {
eval_env->define(formals.back(), eval_next(args, curr_env));
}
assert(!args && "too many args");
return eval_body();
}
if (!args) {
eval_env->define(formals.back(), nullptr);
return eval_body();
}
sp<pair> tail(make_sp<pair>(eval_next(args, curr_env)));
eval_env->define(formals.back(), tail);
while (args) {
sp<pair> new_tail(make_sp<pair>(eval_next(args, curr_env)));
tail->cdr = new_tail;
tail = new_tail;
}
return eval_body();
}