;; Access point for rpn compilation. This defineds represent/find ;; which can be used together with code from ns-utils.ss to create rpn ;; compilers bound to a list of namespaces. (module rpn mzscheme (require-for-syntax "rpn-tx.ss" ;; transformer tools "rep.ss") (require "rep.ss") (provide rpn-compiler-stx) ;; A macro to combine syntax and semantics. (see examples below) ;; This macro is used to generate representatives of the 2 basic ;; forms of compositional syntax: stx-base and stx-state. It is ;; parameterized by: ;; stx-represent -- a macro helper function that maps rpn code -> scheme (from rpn-tx.ss) ;; make-find -- a function that creates a binding closure from a name space spec (define-syntax rpn-compiler-stx (syntax-rules () ((_ language-stx stx-represent make-find) ;; In = syntax + find generator. ;; Create a 'languag-stx' macro, (define-syntax language-stx (syntax-rules () ((_ (language: . delegate-names) find-spec (... ...)) (begin ;; which generates a hidden runtime name resolver used ;; to map symbols to executable code for this language, (define find (make-find 'find-spec (... ...))) ;; and a compile time syntax transformer mapping rpn ;; code to scheme code. (define-syntax (language: stx) (syntax-case stx () ((_ . code) (stx-represent #'code #'find '(language: . delegate-names))))) )))) ))) ;; THE BIG PICTURE ;; ;; These higher order macros are a bit confusing, at least to me, ;; but I believe it's better to structure the code like this than ;; needless copy & paste. This is how they are used: ;; ;; The 'rpn-compiler-stx' macro expands first to the 'ns-base-stx' ;; and 'ns-state-stx' macros, used for 2 main classes of rpn syntax. ;; ;; ns-base-stx.ss : ;; (rpn-compiler-stx ns-base-stx ;; ns-base-rpn ;; make-base-find) ;; ;; ns-state-stx.ss : ;; (rpn-compiler-stx ns-state-stx ;; ns-state-rpn ;; make-state-find) ;; ;; In the second expansion level, these resulting macros are used to ;; bind namespaces to syntax transformers. For example in prj.ss : ;; ;; (ns-state-stx (prj: ;; main semantics tag ;; badnop:) ;; fallback semantics tag ;; ((prj) (store) (state)) ;; main dictionaries ;; ((badnop) (base))) ;; fallback dictionaries ;; ;; Which reads as: create a ns-state-stx compiler (see rpn-tx.ss) ;; called 'prj:'. This compiler creates instances of 'word' (see ;; rep.ss) which is a scheme stack->stack procedure tagged with ;; metadata. This compilermacro is used used like this to create ;; such a word instance: ;; ;; (prj: 1 2 + 'result !) ;; ;; Evaluating the resulting word in a function position, passing it ;; at least one state dictionary argument gives the following: ;; ;; ((prj: 1 2 + 'result !) '()) => (((result . 3))) ;; ;; The 'prj:' macro takes word semantics from the dictionaries (prj) ;; (store) and (state), and attaches 'prj:' semantics tag to the ;; word instance. ;; ;; If it doesn't find a word there, it will look up a word in the ;; dictionaries (badnop) and (base), automaticly lifting it it to ;; pass state. In this case it will produce a word with 'badnop:' ;; semantics. ;; ;; The lifting is done by the 'find' function generated by ;; 'make-state-find'. )