#lang racket/base ;; Macros for defining weak and extensible mappings between sets of values ;; ;;; Copyright 2010, 2011, 2012, 2013 Tony Garnock-Jones ;;; ;;; This file is part of marketplace-dns. ;;; ;;; marketplace-dns is free software: you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License as ;;; published by the Free Software Foundation, either version 3 of the ;;; License, or (at your option) any later version. ;;; ;;; marketplace-dns is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with marketplace-dns. If not, see ;;; . (provide define-mapping) ;; Internal. Extracts macro keywords from a list of arguments. (define-syntax check-defaults (syntax-rules () ((_ fn bn fd bd #:forward-default new-fd rest ...) (check-defaults fn bn new-fd bd rest ...)) ((_ fn bn fd bd #:backward-default new-bd rest ...) (check-defaults fn bn fd new-bd rest ...)) ((_ fn bn fd bd (lhs rhs) ...) (begin (define (fn l) (cond ((eqv? l 'lhs) 'rhs) ... (else (fd l)))) (define (bn r) (cond ((eqv? r 'rhs) 'lhs) ... (else (bd r)))))))) ;; Symbol -> raised exn:fail:contract ;; Used by default to complain when no specific mapping is found. ;; The argument indicates to the user the direction of the mapping. (define (die-with-mapping-name n) (lambda (v) (raise (exn:fail:contract (format "~v: Mapping not found for ~v" n v) (current-continuation-marks))))) ;; (define-mapping ;; { #:forward-default }? ;; { #:backward-default }? ;; ( ) ...) ;; Defines two functions, forward-name and backward-name, which take ;; values from the left-hand-sides of the mappings given as "( ;; )" to the right-hand-sides and vice versa, respectively. ;; ;; If specified, the #:forward-default and #:backward-default exprs ;; should evaluate to a procedure of one argument which can be used ;; for fallback computation of the mapping or for error ;; reporting. They default to raising exn:fail:contract. (define-syntax define-mapping (syntax-rules () ((_ forward-name backward-name rest ...) (check-defaults forward-name backward-name (die-with-mapping-name 'forward-name) (die-with-mapping-name 'backward-name) rest ...))))