#lang scheme/base
(require scheme/dict
(planet untyped/unlib:3/contract)
"base.ss")
(define-struct annotation (id) #:prefab)
(define default-value-procedures
(make-hasheq))
(define value-combinators
(make-hasheq))
(define-syntax define-annotation
(syntax-rules ()
[(_ id default combinator)
(define id
(let ([ans #s(annotation 'id)])
(hash-set! default-value-procedures ans (check-arity 'id 'default-value-procedure default 1))
(hash-set! value-combinators ans (check-arity 'id 'value-combinator combinator 3))
ans))]))
(define (annotation-default annotation)
(hash-ref default-value-procedures annotation))
(define (annotation-combinator annotation)
(hash-ref value-combinators annotation))
(define (check-arity annote-id proc-id proc n)
(if (and (procedure? proc) (procedure-arity-includes? proc n))
proc
(raise-exn exn:fail:contract
(format "define-annotation ~a: ~a: expected procedure of arity ~a, received ~a"
annote-id proc-id n proc))))
(provide define-annotation)
(provide/contract
[struct annotation ([id symbol?])]
[annotation-default (-> annotation? (arity/c 1))]
[annotation-combinator (-> annotation? (arity/c 3))])