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
;
17 int main(int argc
, char* argv
[])
19 String prompt
= "user> ";
21 malEnvPtr
replEnv(new malEnv
);
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 while (s_readLine
.get(prompt
, input
)) {
29 out
= rep(input
, replEnv
);
31 catch (malEmptyInputException
&) {
32 continue; // no output
37 std::cout
<< out
<< "\n";
42 String
rep(const String
& input
, malEnvPtr env
)
44 return PRINT(EVAL(READ(input
), env
));
47 malValuePtr
READ(const String
& input
)
49 return readStr(input
);
52 malValuePtr
EVAL(malValuePtr ast
, malEnvPtr env
)
54 return ast
->eval(env
);
57 String
PRINT(malValuePtr ast
)
59 return ast
->print(true);
62 malValuePtr
APPLY(malValuePtr op
, malValueIter argsBegin
, malValueIter argsEnd
,
65 const malApplicable
* handler
= DYNAMIC_CAST(malApplicable
, op
);
66 MAL_CHECK(handler
!= NULL
,
67 "\"%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
, malEnvPtr env
)
87 return mal::integer(lhs
->value() + rhs
->value());
90 static malValuePtr
builtIn_sub(const String
& name
,
91 malValueIter argsBegin
, malValueIter argsEnd
, malEnvPtr 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
, malEnvPtr 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
, malEnvPtr env
)
115 ARG(malInteger
, lhs
);
116 ARG(malInteger
, rhs
);
117 MAL_CHECK(rhs
->value() != 0, "Division by zero"); \
118 return mal::integer(lhs
->value() / rhs
->value());