diff --git a/goalc/compiler/Compiler.h b/goalc/compiler/Compiler.h index a3ffd4dfdb..de54236d25 100644 --- a/goalc/compiler/Compiler.h +++ b/goalc/compiler/Compiler.h @@ -658,6 +658,7 @@ class Compiler { Val* compile_defglobalconstant(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_defconstant(const goos::Object& form, const goos::Object& rest, Env* env); Val* compile_mlet(const goos::Object& form, const goos::Object& rest, Env* env); + Val* compile_macro_expand(const goos::Object& form, const goos::Object& rest, Env* env); // Math Val* compile_add(const goos::Object& form, const goos::Object& rest, Env* env); diff --git a/goalc/compiler/compilation/Atoms.cpp b/goalc/compiler/compilation/Atoms.cpp index 6e32683ae8..0d24c01c64 100644 --- a/goalc/compiler/compilation/Atoms.cpp +++ b/goalc/compiler/compilation/Atoms.cpp @@ -226,6 +226,9 @@ const std::unordered_map< {"quote", {"", &Compiler::compile_quote}}, {"mlet", {"", &Compiler::compile_mlet}}, {"defconstant", {"", &Compiler::compile_defconstant}}, + {"macro-expand", + {"Displays the expanded form of a macro without evaluating it.", + &Compiler::compile_macro_expand}}, // OBJECT // {"current-method-type", {"", &Compiler::compile_current_method_type}}, diff --git a/goalc/compiler/compilation/Macro.cpp b/goalc/compiler/compilation/Macro.cpp index b0d02b0dbf..9db18a99a3 100644 --- a/goalc/compiler/compilation/Macro.cpp +++ b/goalc/compiler/compilation/Macro.cpp @@ -265,6 +265,21 @@ Val* Compiler::compile_mlet(const goos::Object& form, const goos::Object& rest, return result; } +Val* Compiler::compile_macro_expand(const goos::Object& form, const goos::Object& rest, Env* env) { + auto macro = pair_car(rest); + goos::Object macro_obj; + if (!try_getting_macro_from_goos(pair_car(macro), ¯o_obj)) { + throw_compiler_error(form, "{} is not a macro.", pair_car(macro).print()); + } + // the pretty printer doesn't support macro objects, so we use the pair + auto result = goos::Object(macro); + while (expand_macro_once(result, &result, env)) { + } + auto code = pretty_print::to_string(result); + lg::print("{}\n", code); + return get_none(); +} + bool Compiler::expand_macro_once(const goos::Object& src, goos::Object* out, Env*) { if (!src.is_pair()) { return false;