Eval: Change (macroexpand) into (macroexpand-1)
This commit is contained in:
@@ -88,12 +88,7 @@ ValuePtr Eval::evalFn(const ValueVector& nodes, EnvironmentPtr env)
|
||||
return makePtr<Lambda>(bindings, *std::next(nodes.begin()), env);
|
||||
}
|
||||
|
||||
ValuePtr Eval::evalMacroExpand(const ValueVector& nodes, EnvironmentPtr env)
|
||||
{
|
||||
CHECK_ARG_COUNT_IS("macroexpand", nodes.size(), 1);
|
||||
|
||||
return macroExpand(nodes.front(), env);
|
||||
}
|
||||
// -----------------------------------------
|
||||
|
||||
// (quasiquoteexpand x)
|
||||
ValuePtr Eval::evalQuasiQuoteExpand(const ValueVector& nodes)
|
||||
@@ -237,6 +232,53 @@ void Eval::evalLet(const ValueVector& nodes, EnvironmentPtr env)
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// (x y z)
|
||||
static bool isMacroCall(ValuePtr ast, EnvironmentPtr env)
|
||||
{
|
||||
auto list = dynamic_cast<List*>(ast.get());
|
||||
|
||||
if (list == nullptr || list->empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto front = list->front().get();
|
||||
|
||||
if (!is<Symbol>(front)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto symbol = dynamic_cast<Symbol*>(front)->symbol();
|
||||
auto value = env->get(symbol).get();
|
||||
|
||||
if (!is<Macro>(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Eval::evalMacroExpand1(const ValueVector& nodes, EnvironmentPtr env)
|
||||
{
|
||||
CHECK_ARG_COUNT_IS("macroexpand-1", nodes.size(), 1, void());
|
||||
|
||||
if (!isMacroCall(nodes.front(), env)) {
|
||||
m_ast = nodes.front();
|
||||
m_env = env;
|
||||
return;
|
||||
}
|
||||
|
||||
auto list = std::static_pointer_cast<List>(nodes.front());
|
||||
|
||||
auto value = env->get(std::static_pointer_cast<Symbol>(list->front())->symbol());
|
||||
auto lambda = std::static_pointer_cast<Lambda>(value);
|
||||
|
||||
m_ast = lambda->body();
|
||||
m_env = Environment::create(lambda, list->rest());
|
||||
return; // TCO
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
static bool isSymbol(ValuePtr value, const std::string& symbol)
|
||||
{
|
||||
if (!is<Symbol>(value.get())) {
|
||||
@@ -331,6 +373,8 @@ void Eval::evalQuasiQuote(const ValueVector& nodes, EnvironmentPtr env)
|
||||
return; // TCO
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// (while true body...)
|
||||
void Eval::evalWhile(const ValueVector& nodes, EnvironmentPtr env)
|
||||
{
|
||||
|
||||
+4
-47
@@ -83,9 +83,6 @@ ValuePtr Eval::evalImpl()
|
||||
if (symbol == "fn*") {
|
||||
return evalFn(nodes, env);
|
||||
}
|
||||
if (symbol == "macroexpand") {
|
||||
return evalMacroExpand(nodes, env);
|
||||
}
|
||||
if (symbol == "quasiquoteexpand") {
|
||||
return evalQuasiQuoteExpand(nodes);
|
||||
}
|
||||
@@ -108,6 +105,10 @@ ValuePtr Eval::evalImpl()
|
||||
evalLet(nodes, env);
|
||||
continue; // TCO
|
||||
}
|
||||
if (symbol == "macroexpand-1") {
|
||||
evalMacroExpand1(nodes, env);
|
||||
continue; // TCO
|
||||
}
|
||||
if (symbol == "quasiquote") {
|
||||
evalQuasiQuote(nodes, env);
|
||||
continue; // TCO
|
||||
@@ -202,50 +203,6 @@ ValuePtr Eval::evalHashMap(ValuePtr ast, EnvironmentPtr env)
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
// (x y z)
|
||||
bool Eval::isMacroCall(ValuePtr ast, EnvironmentPtr env)
|
||||
{
|
||||
auto list = dynamic_cast<List*>(ast.get());
|
||||
|
||||
if (list == nullptr || list->empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto front = list->front().get();
|
||||
|
||||
if (!is<Symbol>(front)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto symbol = dynamic_cast<Symbol*>(front)->symbol();
|
||||
auto value = env->get(symbol).get();
|
||||
|
||||
if (!is<Macro>(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// (x y z)
|
||||
ValuePtr Eval::macroExpand(ValuePtr ast, EnvironmentPtr env)
|
||||
{
|
||||
while (isMacroCall(ast, env)) {
|
||||
auto list = std::static_pointer_cast<List>(ast);
|
||||
|
||||
auto value = env->get(std::static_pointer_cast<Symbol>(list->front())->symbol());
|
||||
auto lambda = std::static_pointer_cast<Lambda>(value);
|
||||
|
||||
m_ast = lambda->body();
|
||||
m_env = Environment::create(lambda, list->rest());
|
||||
ast = evalImpl();
|
||||
}
|
||||
|
||||
return ast;
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
|
||||
ValuePtr Eval::apply(ValuePtr function, const ValueVector& nodes)
|
||||
{
|
||||
if (!is<Function>(function.get())) {
|
||||
|
||||
+1
-4
@@ -31,13 +31,9 @@ private:
|
||||
ValuePtr evalVector(ValuePtr ast, EnvironmentPtr env);
|
||||
ValuePtr evalHashMap(ValuePtr ast, EnvironmentPtr env);
|
||||
|
||||
bool isMacroCall(ValuePtr ast, EnvironmentPtr env);
|
||||
ValuePtr macroExpand(ValuePtr ast, EnvironmentPtr env);
|
||||
|
||||
ValuePtr evalDef(const ValueVector& nodes, EnvironmentPtr env);
|
||||
ValuePtr evalDefMacro(const ValueVector& nodes, EnvironmentPtr env);
|
||||
ValuePtr evalFn(const ValueVector& nodes, EnvironmentPtr env);
|
||||
ValuePtr evalMacroExpand(const ValueVector& nodes, EnvironmentPtr env);
|
||||
ValuePtr evalQuasiQuoteExpand(const ValueVector& nodes);
|
||||
ValuePtr evalQuote(const ValueVector& nodes);
|
||||
ValuePtr evalTry(const ValueVector& nodes, EnvironmentPtr env);
|
||||
@@ -45,6 +41,7 @@ private:
|
||||
void evalDo(const ValueVector& nodes, EnvironmentPtr env);
|
||||
void evalIf(const ValueVector& nodes, EnvironmentPtr env);
|
||||
void evalLet(const ValueVector& nodes, EnvironmentPtr env);
|
||||
void evalMacroExpand1(const ValueVector& nodes, EnvironmentPtr env);
|
||||
void evalQuasiQuote(const ValueVector& nodes, EnvironmentPtr env);
|
||||
void evalWhile(const ValueVector& nodes, EnvironmentPtr env);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user