diff --git a/src/eval-special-form.cpp b/src/eval-special-form.cpp index 0fcd7f6..804b435 100644 --- a/src/eval-special-form.cpp +++ b/src/eval-special-form.cpp @@ -88,12 +88,7 @@ ValuePtr Eval::evalFn(const ValueVector& nodes, EnvironmentPtr env) return makePtr(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(ast.get()); + + if (list == nullptr || list->empty()) { + return false; + } + + auto front = list->front().get(); + + if (!is(front)) { + return false; + } + + auto symbol = dynamic_cast(front)->symbol(); + auto value = env->get(symbol).get(); + + if (!is(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(nodes.front()); + + auto value = env->get(std::static_pointer_cast(list->front())->symbol()); + auto lambda = std::static_pointer_cast(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(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) { diff --git a/src/eval.cpp b/src/eval.cpp index 84e4943..ec632af 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -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(ast.get()); - - if (list == nullptr || list->empty()) { - return false; - } - - auto front = list->front().get(); - - if (!is(front)) { - return false; - } - - auto symbol = dynamic_cast(front)->symbol(); - auto value = env->get(symbol).get(); - - if (!is(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(ast); - - auto value = env->get(std::static_pointer_cast(list->front())->symbol()); - auto lambda = std::static_pointer_cast(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.get())) { diff --git a/src/eval.h b/src/eval.h index b6cd48e..c1da50c 100644 --- a/src/eval.h +++ b/src/eval.h @@ -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);