(module macro-prim mzscheme (require "ns-state-stx.ss" ;; for creating macro-prim: "ns.ss" ;; for the (macro-prim) namespace "composite.ss" "badnop.ss") ;; compiler utilites we inherit from (provide macro-prim:) ;; *** MACRO-PRIM DICT *** ;; The forth compiler is implemented as a collection of functions ;; that act on a state buffer containing assembly language ;; instructions. These functions are called macros, and will reside ;; in the macro dictionary. ;; Before we can implement macros, we need to define some state ;; access words, which we group in the (macro-prim) namespace. The ;; state is a buffer (stack) with assembly instructions, last ;; instruction on top. ;; (ns-new '(macro-prim)) (compositions (badnop) badnop: (try-need-buf ('(asm-buffer-empty) throw) try) ) (compositions (macro-prim) badnop: ;; Basic access. (last (dup (car) dip) try-need-buf) ;; copy last instruction (last> (uncons) try-need-buf) ;; pop last instruction (>asm cons) ;; compile last instruction ;; Used for backtracking: ambiguously execute one of 2 macros with ;; continuation saved in the asm buffer. this saves the ;; continuation as '(continuation . ) ;; ( now later -- ? ) (amb-run/s -rot ;; asm now later ('cont swons swons) ;; saves continuation to asm buffer amb-choose run) (require swap ('cont swap swap dict-find ;; use asm buffer as assoc-list run) ;; execute the continuation unless) ) ;; Now we can define primtive macro syntax using state syntax and ;; the (macro-prim) namespace. (ns-state-stx (macro-prim: badnop:) ((macro-prim) (state)) ((badnop) (base))) ;; Here we first augment the (macro-prim) dictionary with some ;; utility functions. These are not in the (macro) dict, so are not ;; accessible from the forth macro language, but can be used as ;; utilities to define primitive macros. (compositions (macro-prim) macro-prim: (op>asm cons reverse >asm) ;; These belong in this dictionary, but need to be provided by ;; target-specific code. (compile '(cw) op>asm) (literal '(qw) op>asm) ) )