;; WRITER MONAD ;; i sort of reinvented this without any theoretical background, so my ;; terminology is a bit off, and the implementation a bit ad-hoc ;; probably. by 'lift' i mean a combination of 'map' and 'join' ;; http://en.wikipedia.org/wiki/Monads_in_functional_programming ;; The map operation, with type (t -> u) -> (M t -> M u), takes a function ;; between two types and produces a function that does the "same ;; thing" to values in the monad. ;; The join operation, with type M (M t) -> M t, "flattens" two layers ;; of monadic information into one. ;; i use only variants of the writer monad for compilation, and the ;; state monad for target state storage. ;; WRITER MONAD ;; these types are lifted to (asm . stack) -> (asm . stack) ;; - pure rewrite: asm -> asm ;; - stateful forward: stack -> (asm . stack) ;; - stateful rewrite: (asm . stack) -> (asm . stack) ;; - constant: -> asm ;; the 'statuful' macros do not look at previous output, while the ;; 'rewrite' macros do. ;; these functions operate on primitive stack operations (procedures) ;; lifts stack -> (asm . stack) ;; a.k.a. the Writer Monad (module writer mzscheme (require ;; "vm.ss" ;; "word.ss" "rep.ss" "list-utils.ss" (lib "match.ss")) (provide (all-defined)) ;; this is no longer used: i simplified the macros to just use a ;; '>asm' word instead of a separate writer class. i leave it here ;; for reference. ;; (define (lift-writer macro) ;; (lambda (old-code . stack) ;; (unpack (new-code . new-stack) (apply macro stack) ;; (let next ((n new-code) ;; (o old-code)) ;; (if (null? n) ;; (pack o new-stack) ;; (next (cdr n) ;; (cons (car n) o))))))) )