It's especially hard when you don't have semantics for your language outside of what your interpreter does. Then the semantics of the language in the book are plain bad: there is only dynamic scoping (oh, and the book often has plain misinformation - the provided definition of "lexical scoping" is wrong), and setting a local variable only affects the innermost LET if you nest environments, since the interpreter deep-copies environments (as it does with everything, to cope with lack of GC).
The book also uses something more like fexprs than macros, which I don't have an opinion _outside of this book_ on with regards to language UX, but fexprs are generally harder to compile. That is in part because they control if/when their arguments are evaluated, but the fexpr-alike things here do not (instead "Q-expressions" delay evaluation like QUOTE). You still would want to do something about calls to EVAL though. The fexpr system _in this book_ also does have bad UX: it only incidentally works with dynamic binding (Shutt's lexically scoped fexprs explicitly pass the environment around) and it also leaks every variable binding from the fexpr function into what it evaluates.
The book also just doesn't cover compilers, so you're doing that slog on your own.