private/mpost-type-funs.rkt
#lang racket
(provide type-> type-or check-type current-stack fold/type)
;;--------------------------------
(require racket/match)
(require (planet wcy/anaphora))
(require "mpost-utils.rkt")
(define ((type-> . in-types) . in-targets)
  (let lp ((types  in-types)
           (targets in-targets))
    (cond
     ((and (null? targets) (null? types)) #t)
     ((and (null? targets) (not (null? types))) types)
     ((and (not (null? targets)) (null? types))
      (error "more arguments are provided." in-types in-targets))
     ((and (not (null? targets)) (not (null? types)))
      (if (eq? (car types) (car targets)) 
          (lp (cdr types) (cdr targets)) 
          #f))
     (else (error 'never-goes-here)))))
(define ((type-or . type-defs) . objs)
  (for/or ((f (in-list type-defs)))
          (apply f objs)))
(define current-stack (make-parameter '()))
(define ((check-type . type-defs) . objs)
  (aif (aand (apply (apply type-or type-defs) objs)
             (return-type it)) 
       it
       (error (string-append
               "type error:\n"
               (pretty-format (current-stack)) "\n"
               "given types:" (pretty-format objs) "\n")) ))
(define (return-type type)
  (match type
    ((list v) v)
    (else #f)))
(define ((fold/type f2) x1 x2 . xs)
  (if (null? xs)
      (f2 x1 x2)
      (aif (return-type (f2 x1 x2))
           (apply (fold/type f2) it xs)
           #f)))