3 #include "Environment.h"
10 malValuePtr
READ(const String
& input
);
11 String
PRINT(malValuePtr ast
);
13 static ReadLine
s_readLine("~/.mal-history");
14 static malBuiltIn::ApplyFunc
15 builtIn_add
, builtIn_sub
, builtIn_mul
, builtIn_div
, builtIn_hash_map
;
17 int main(int argc
, char* argv
[])
19 String prompt
= "user> ";
22 replEnv
.set("+", mal::builtin("+", &builtIn_add
));
23 replEnv
.set("-", mal::builtin("-", &builtIn_sub
));
24 replEnv
.set("*", mal::builtin("+", &builtIn_mul
));
25 replEnv
.set("/", mal::builtin("/", &builtIn_div
));
26 replEnv
.set("hash-map", mal::builtin("hash-map", &builtIn_hash_map
));
27 while (s_readLine
.get(prompt
, input
)) {
30 out
= rep(input
, replEnv
);
32 catch (malEmptyInputException
&) {
33 continue; // no output
38 std::cout
<< out
<< "\n";
43 String
rep(const String
& input
, malEnv
& env
)
45 return PRINT(EVAL(READ(input
), env
));
48 malValuePtr
READ(const String
& input
)
50 return readStr(input
);
53 malValuePtr
EVAL(malValuePtr ast
, malEnv
& env
)
55 return ast
->eval(env
);
58 String
PRINT(malValuePtr ast
)
60 return ast
->print(true);
63 malValuePtr
APPLY(malValuePtr op
, malValueIter argsBegin
, malValueIter argsEnd
,
66 const malApplicable
* handler
= DYNAMIC_CAST(malApplicable
, op
);
67 ASSERT(handler
!= NULL
, "\"%s\" is not applicable", op
->print(true).c_str());
69 return handler
->apply(argsBegin
, argsEnd
, env
);
72 #define ARG(type, name) type* name = VALUE_CAST(type, *argsBegin++)
74 #define CHECK_ARGS_IS(expected) \
75 checkArgsIs(name.c_str(), expected, std::distance(argsBegin, argsEnd))
77 #define CHECK_ARGS_BETWEEN(min, max) \
78 checkArgsBetween(name.c_str(), min, max, std::distance(argsBegin, argsEnd))
81 static malValuePtr
builtIn_add(const String
& name
,
82 malValueIter argsBegin
, malValueIter argsEnd
, malEnv
& env
)
87 return mal::integer(lhs
->value() + rhs
->value());
90 static malValuePtr
builtIn_sub(const String
& name
,
91 malValueIter argsBegin
, malValueIter argsEnd
, malEnv
& env
)
93 int argCount
= CHECK_ARGS_BETWEEN(1, 2);
96 return mal::integer(- lhs
->value());
99 return mal::integer(lhs
->value() - rhs
->value());
102 static malValuePtr
builtIn_mul(const String
& name
,
103 malValueIter argsBegin
, malValueIter argsEnd
, malEnv
& env
)
106 ARG(malInteger
, lhs
);
107 ARG(malInteger
, rhs
);
108 return mal::integer(lhs
->value() * rhs
->value());
111 static malValuePtr
builtIn_div(const String
& name
,
112 malValueIter argsBegin
, malValueIter argsEnd
, malEnv
& env
)
115 ARG(malInteger
, lhs
);
116 ARG(malInteger
, rhs
);
117 ASSERT(rhs
->value() != 0, "Division by zero"); \
118 return mal::integer(lhs
->value() / rhs
->value());
121 static malValuePtr
builtIn_hash_map(const String
& name
,
122 malValueIter argsBegin
, malValueIter argsEnd
, malEnv
& env
)
124 return mal::hash(argsBegin
, argsEnd
);