aboutsummaryrefslogtreecommitdiff
(functor ((algebraic-structures monad) (M (pure map1 map2 map apply >>=)))
    (pure map1 map2 map apply >>= do)
  (import (rename scheme
                  (apply scheme:apply)
                  (map scheme:map)
                  (do scheme:do))
          (chicken base)
          (only M pure map1 map2 map apply >>=))
  (import-for-syntax matchable
                     (chicken syntax)
                     (only (srfi 1) every last))

  (define-syntax do
    (er-macro-transformer
     (lambda (expr rename compare)
       (match expr
         [(_ body ...)
          (foldr (lambda (binding acc)
                   (match binding
                     [(var stx expr)
                      (if (and (symbol? var)
                               (symbol? stx)
                               (compare stx (rename '<-)))
                          `(,(rename '>>=) ,expr (,(rename 'lambda) (,var) ,acc))
                          `(,(rename '>>=) ,binding (,(rename 'lambda) (_) ,acc)))]
                     [(let-stx var =-stx expr)
                      (cond ((and (symbol? var)
                                  (symbol? let-stx) (compare let-stx 'let)
                                  (symbol? =-stx) (compare =-stx '=))
                             `((,(rename 'lambda) (,var) ,acc) ,expr))
                            ((and (list? var)
                                  (every symbol? var)
                                  (symbol? let-stx) (compare let-stx 'let-values)
                                  (symbol? =-stx) (compare =-stx '=))
                             `(,(rename 'receive) ,var ,expr ,acc))
                            (else
                             `(,(rename '>>=) ,binding (,(rename 'lambda) (_) ,acc))))]
                     [expr
                      `(,(rename '>>=) ,expr (,(rename 'lambda) (_) ,acc))]))
                 (last body)
                 (butlast body))])))))