Also you can really, really change both syntax and semantics: https://docs.racket-lang.org/2d/
Although not similar technically speaking, Graal/Truffle is a better comparison in spirit, IMO. But Graal/Truffle is hugely complex, with many many man-hours in it.
Classic example and discussion: https://www.reddit.com/r/programming/comments/i1slm/comment/... https://www.hashcollision.org/brainfudge/index.html
Also you can really, really change both syntax and semantics: https://docs.racket-lang.org/2d/ Exactly, racket give you much more freedom because of this, I don't know the use cases but it's indeed more powerful. A comparison with Truffle would be great! I wonder if a higher level/simpler but less powerful abstraction on top of Truffle could bridge the difficulty gap.
For building DSLs the following features are useful: Infix/postfix functions, Operator overloading, Varargs/spread operator, Scope controling what is allowed. Other features??