-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
builtin-functions.cpp
145 lines (113 loc) · 3.78 KB
/
builtin-functions.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
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
#include "environment.h"
#include <unicode/unistr.h>
#include <iostream>
using namespace icu;
namespace my {
extern bool value_isTrue(const value_t& value) ;
// Function MACROEXPAND, MACROEXPAND-1
extern value_t macroExpand1(EnvPtr args);
/* https://hyotang666.github.io/archives/structure-vs-class.html
DEFSTRUCT で自動生成される名前とビルトイン関数の名前が、チグハグ
predicate named name-p,
-- (typep subclass 'my-class) があれば足りる
constructor function named make-constructor-name
-- MAKE-INSTANCE があれば不要では?
copier function named copy-constructor-name
-- COPY-STRUCTURE があれば不要
STRUCT名-SLOT名というアクセサ. 総称関数ではない。slot名だけのほうがいい?
(slot-value c 'slot) これでアクセサがなくても値を取れる
*/
//////////////////////////////////////////////////////////////////////////
// <object>
// ビルトイン関数
// Function NOT
value_t do_not(my::EnvPtr args) {
my::value_t x = args->find_value("X");
return value_isTrue(x) ? my::nilValue : my::trueValue;
}
// ビルトイン関数
// 標準出力に出力
// Function WRITE, PRIN1, PRINT, PPRINT, PRINC
value_t do_print(my::EnvPtr args) {
my::value_t x = args->find_value("X");
PRINT(x, std::cout);
std::cout << "\n";
return my::nilValue;
}
// (setq a 1) => 1
// (list a 2) => (1 2)
value_t do_list(EnvPtr args) {
// 呼び出し時に評価済み
return args->find_value("OBJECTS");
}
//////////////////////////////////////////////////////////////////////////
// <number>
// ビルトイン関数
value_t do_add(EnvPtr args)
{
value_t x = args->find_value("X"); double xv = std::get<double>(x);
value_t y = args->find_value("Y"); double yv = std::get<double>(y);
return xv + yv;
}
value_t do_multiply(EnvPtr args)
{
value_t x = args->find_value("X"); double xv = std::get<double>(x);
value_t y = args->find_value("Y"); double yv = std::get<double>(y);
return xv * yv;
}
my::value_t do_1minus(my::EnvPtr args) {
my::value_t x = args->find_value("X");
double v = std::get<double>(x);
return v - 1;
}
// @return T or NIL
my::value_t do_gt(my::EnvPtr args) {
double x = std::get<double>(args->find_value("X"));
double y = std::get<double>(args->find_value("Y"));
return x > y ? trueValue : nilValue;
}
//////////////////////////////////////////////////////////////////////////
// <function>
value_t do_mapcar(EnvPtr args)
{
FuncPtr func = VALUE_CAST_CHECKED(function, args->find_value("FUNC"));
ListPtr list = VALUE_CAST_CHECKED(class list, args->find_value("LIST"));
std::shared_ptr<cons> ret = std::make_shared<cons>();
for (const auto& v : *list) {
// ここは eval しなおさない
std::shared_ptr<cons> args = std::make_shared<cons>();
args->append(v);
ret->append( func->apply(args) );
}
if (ret->empty())
return nilValue;
else
return ret;
}
struct BuiltinFunc {
const UnicodeString& name;
const UnicodeString& params;
std::function<my::value_t(my::EnvPtr)> func;
};
static const BuiltinFunc funcs[] = {
{"MACROEXPAND-1", "(form)", my::macroExpand1 },
// <object>
{"NOT", "(x)", my::do_not },
{"PRINT", "(x)", my::do_print },
{"LIST", "(&rest objects)", do_list },
// <number>
{"+", "(x y)", my::do_add },
{"*", "(x y)", my::do_multiply },
{"1-", "(x)", my::do_1minus },
{">", "(x y)", my::do_gt },
// <function>
{"MAPCAR", "(func list)", do_mapcar },
};
void setup_functions()
{
my::globalEnv->set_value("T", my::trueValue, true);
my::globalEnv->set_value("NIL", my::nilValue, true);
for (const auto& f : funcs)
define_function(f.name, f.params, f.func);
}
} // namespace my