#lang racket/base (require (for-syntax racket/base)) (provide (for-syntax eh-first-accumulate eh-first-accumulate! eh-pre-accumulate eh-pre-accumulate! eh-post-accumulate eh-post-accumulate! eh-post-group eh-post-group! clause-counter get-new-clause! is-clause-id-sym? lift-rest lift-rest!)) (define-syntax-rule (define-dynamic-accumulator-parameter parameter-name name!) (begin (define-for-syntax parameter-name (make-parameter #f)) (define-for-syntax (name! name . args) (unless (parameter-name) (raise-syntax-error name (string-append (symbol->string name) " used outside of ~seq-no-order"))) (apply (parameter-name) args)))) (define-dynamic-accumulator-parameter eh-first-accumulate eh-first-accumulate!) (define-dynamic-accumulator-parameter eh-pre-accumulate eh-pre-accumulate!) (define-dynamic-accumulator-parameter eh-post-group eh-post-group!) (define-dynamic-accumulator-parameter eh-post-accumulate eh-post-accumulate!) (define-dynamic-accumulator-parameter lift-rest lift-rest!) ;; This is a crude hack. (define-for-syntax (is-clause-id-sym? id-sym) (and (symbol? id-sym) (regexp-match #px"^ -clause-.* $" (symbol->string id-sym)))) (define-for-syntax clause-counter (make-parameter #f)) (define-for-syntax (get-new-clause!) (unless clause-counter (error "Use get-new-clause! within (parameterize ([clause-counter …]) …)")) (datum->syntax #'here ;; keep the spaces, they allow us to recognize clauses later. (string->symbol (format " -clause-~a " ((clause-counter))))))