2 #include "Environment.h"
3 #include "StaticList.h"
9 #define CHECK_ARGS_IS(expected) \
10 checkArgsIs(name.c_str(), expected, \
11 std::distance(argsBegin, argsEnd))
13 #define CHECK_ARGS_BETWEEN(min, max) \
14 checkArgsBetween(name.c_str(), min, max, \
15 std::distance(argsBegin, argsEnd))
17 #define CHECK_ARGS_AT_LEAST(expected) \
18 checkArgsAtLeast(name.c_str(), expected, \
19 std::distance(argsBegin, argsEnd))
21 static String
printValues(malValueIter begin
, malValueIter end
,
22 const String
& sep
, bool readably
);
24 static StaticList
<malBuiltIn
*> handlers
;
26 #define ARG(type, name) type* name = VALUE_CAST(type, *argsBegin++)
28 #define FUNCNAME(uniq) builtIn ## uniq
29 #define HRECNAME(uniq) handler ## uniq
30 #define BUILTIN_DEF(uniq, symbol) \
31 static malBuiltIn::ApplyFunc FUNCNAME(uniq); \
32 static StaticList<malBuiltIn*>::Node HRECNAME(uniq) \
33 (handlers, new malBuiltIn(symbol, FUNCNAME(uniq))); \
34 malValuePtr FUNCNAME(uniq)(const String& name, \
35 malValueIter argsBegin, malValueIter argsEnd, malEnvPtr env)
37 #define BUILTIN(symbol) BUILTIN_DEF(__LINE__, symbol)
39 #define BUILTIN_ISA(symbol, type) \
42 return mal::boolean(DYNAMIC_CAST(type, *argsBegin)); \
45 #define BUILTIN_INTOP(op, checkDivByZero) \
48 ARG(malInteger, lhs); \
49 ARG(malInteger, rhs); \
50 if (checkDivByZero) { \
51 ASSERT(rhs->value() != 0, "Division by zero"); \
53 return mal::integer(lhs->value() op rhs->value()); \
56 BUILTIN_ISA("list?", malList
);
58 BUILTIN_INTOP(+, false);
59 BUILTIN_INTOP(/, true);
60 BUILTIN_INTOP(*, false);
61 BUILTIN_INTOP(%, true);
65 int argCount
= CHECK_ARGS_BETWEEN(1, 2);
68 return mal::integer(- lhs
->value());
72 return mal::integer(lhs
->value() - rhs
->value());
81 return mal::boolean(lhs
->value() <= rhs
->value());
87 const malValue
* lhs
= (*argsBegin
++).ptr();
88 const malValue
* rhs
= (*argsBegin
++).ptr();
90 return mal::boolean(lhs
->isEqualTo(rhs
));
96 if (*argsBegin
== mal::nilValue()) {
97 return mal::integer(0);
100 ARG(malSequence
, seq
);
101 return mal::integer(seq
->count());
107 ARG(malSequence
, seq
);
109 return mal::boolean(seq
->isEmpty());
115 return EVAL(*argsBegin
, env
->getRoot());
120 return mal::hash(argsBegin
, argsEnd
);
125 return mal::string(printValues(argsBegin
, argsEnd
, " ", true));
130 std::cout
<< printValues(argsBegin
, argsEnd
, " ", false) << "\n";
131 return mal::nilValue();
136 std::cout
<< printValues(argsBegin
, argsEnd
, " ", true) << "\n";
137 return mal::nilValue();
140 BUILTIN("read-string")
145 return readStr(str
->value());
151 ARG(malString
, filename
);
153 std::ios_base::openmode openmode
=
154 std::ios::ate
| std::ios::in
| std::ios::binary
;
155 std::ifstream
file(filename
->value().c_str(), openmode
);
156 ASSERT(!file
.fail(), "Cannot open %s", filename
->value().c_str());
159 data
.reserve(file
.tellg());
160 file
.seekg(0, std::ios::beg
);
161 data
.append(std::istreambuf_iterator
<char>(file
.rdbuf()),
162 std::istreambuf_iterator
<char>());
164 return mal::string(data
);
169 return mal::string(printValues(argsBegin
, argsEnd
, "", false));
172 void installCore(malEnvPtr env
) {
173 for (auto it
= handlers
.begin(), end
= handlers
.end(); it
!= end
; ++it
) {
174 malBuiltIn
* handler
= *it
;
175 env
->set(handler
->name(), handler
);
179 static String
printValues(malValueIter begin
, malValueIter end
,
180 const String
& sep
, bool readably
)
185 out
+= (*begin
)->print(readably
);
189 for ( ; begin
!= end
; ++begin
) {
191 out
+= (*begin
)->print(readably
);