Are you talking about the tools that eg Lisp has to manipulate arbitrary ASTs, or are you talking about the AST required to represent Lisp code?
Racket (a Lisp) and ML-family languages like Haskell are really good at manipulating arbitrary ASTs and similar structures. ML was even invented to do exactly that, the letters stand for meta-language.
I do agree that the structures you need to represent Haskell would be rather complicated: Haskell is a rather complex language after all.
I'm not sure what you mean by having to bootstrap meaningful things endlessly? I can understand that eg C is pretty limited, so you have to put in lots of effort to bootstrap to something meaningfully. But most higher level languages would be doing just fine. And you can also use libraries:
Eg no need to write your own parser from scratch, if you can just use a parser combinator library like parsec. Also no need for a beginner to write native code generation from scratch: just use a library to interface with llvm.
Racket (a Lisp) and ML-family languages like Haskell are really good at manipulating arbitrary ASTs and similar structures. ML was even invented to do exactly that, the letters stand for meta-language.
I do agree that the structures you need to represent Haskell would be rather complicated: Haskell is a rather complex language after all.
I'm not sure what you mean by having to bootstrap meaningful things endlessly? I can understand that eg C is pretty limited, so you have to put in lots of effort to bootstrap to something meaningfully. But most higher level languages would be doing just fine. And you can also use libraries:
Eg no need to write your own parser from scratch, if you can just use a parser combinator library like parsec. Also no need for a beginner to write native code generation from scratch: just use a library to interface with llvm.