Hi all, I'm working on a family of languages in Racket, and I'm running into a conceptual issue with the information flow of the project. I have a standard core language whose syntax is s-expressions, with some macros in the expander. Then, there is a surface language (compiled into s-expressions with brag) which directly translates into the core language. There will also be other surface languages in the future, forming a tower/tree of languages that compile into simpler ones, so I want to make sure I get this pattern right.
Conceptually, I would want the surface language to fully "compile" into the core language before the core language tries to do anything. As I develop the surface language, I don't think I should have to concern myself with the inner workings of the core language; I should be able to just produce core language code, and then have the core language handle it from there. I find myself running into an issue, however, where the core language starts to do computations before the translation is fully complete. This is an issue because the macros of the core language are taking in the syntax of the surface language which hasn't been translated yet, and so the core language doesn't recognize this syntax and breaks. As a small example, consider the following: core-language-expander.rkt (define-syntax (A-core stx) (syntax-parse stx #:datum-literals (b-core) [(A-core (b-core x)) #'(printf "A-core got value ~a.~n" x)])) surface-language-expander.rkt (define-syntax-rule (b-surface x) (b-core x)) (define-syntax (A-surface stx) (syntax-parse stx [(A-surface expr) #'(A-core expr)])) Here, if we call `(A-surface (b-surface "hello"))`, we would want it to take the `A-surface`, and convert it into `A-core`, and then expand `(b-surface "hello")`. Since `A-core` is implemented as a macro, though, it takes `(b-surface "hello")` unexpanded, and so tries to evaluate `(A-core (b-surface "hello"))`, which fails. Since `b-core` isn't defined as a function/macro in the core language (it is just a piece of syntax used in `A-core`), we can't just evaluate `(b-surface "hello")` as a value before passing it in. If we try using `local-expand` or something similar to handle the expansion as syntax, there isn't an obvious way to make it only expand macros defined in the surface language expander (and not those defined in the core language expander), which turns out to be an issue in my case. Do any of you recommend a resource for understanding the strategy of taking a stack of languages and compiling down one layer at a time? It seems like the notion of a tower of languages would be fairly natural, yet the only success I have had is with some hacks with recursive local-expand that feel extremely unnatural, and also require further hacks to get around things like syntax-tainting. Thanks so much! Thomas Del Vecchio -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/26f44e6d-f1f8-465e-9639-6cd6afeffa31n%40googlegroups.com.