[plt-scheme] re-providing a contract

From: Doug Orleans (dougorleans at gmail.com)
Date: Tue Apr 15 16:58:56 EDT 2008

Robby Findler writes:
 > Can you change the original program to export the contracts and then
 > just re-use them?

Well, the point of this silly little exercise was to see how it would
look without changing the original package.  What I was actually doing
was adding https support to net/url, so if I were going to propose a
change to net/url, I'd just ask for https support directly.

Anyway, here's what I ended up with.  Should I make a PLaneT package?

--dougorleans at gmail.com

#lang scheme

(require scheme/unit)
(require net/url-sig)
(require net/url-unit)
(require net/tcp-sig)
(require net/tcp-unit)
(require net/ssl-tcp-unit)
(require (only-in net/url url-scheme))

(define-unit-binding ssl-tcp@
  (make-ssl-tcp@ #f #f #f #f #f #f #f)
  (import) (export tcp^))

(define-syntax define-wrapped-procs
  (syntax-rules ()
    ((_ sig unit (proc dom ...) ...)
       (require (except-in net/url proc ...))
       (provide (all-from-out net/url))
       (define-signature sig (proc ...))
       (define-unit unit
         (import (tag tcp (prefix tcp: url^))
                 (tag ssl-tcp (prefix ssl-tcp: url^)))
         (export sig)
         (define/wrapped proc)
        (proc ((url? dom ...) ((listof string?)) . ->* . input-port?))

(define-wrapped-procs wrapped^ wrapped@
  (post-pure-port (or/c false/c bytes?))
  (post-impure-port bytes?)
  (put-pure-port (or/c false/c bytes?))
  (put-impure-port bytes?))

(define-compound-unit wrapped+urls@
  (import) (export WRAPPED)
  (link (((TCP : url^))
          (import) (export url^)
          (link tcp@ url@)))
        (((SSL-TCP : url^))
          (import) (export url^)
          (link ssl-tcp@ url@)))
        (((WRAPPED : wrapped^))
         wrapped@ (tag tcp TCP) (tag ssl-tcp SSL-TCP))))

(define-values/invoke-unit/infer wrapped+urls@)

(define-for-syntax (symbol-append . symbols)
  (string->symbol (apply string-append (map symbol->string symbols))))

(define-for-syntax (syntax-prefix sym stx)
  (datum->syntax stx (symbol-append sym (syntax-e stx))))

(define-syntax (define/wrapped stx)
  (syntax-case stx ()
    ((define/wrapped name)
     (with-syntax ((tcp:name (syntax-prefix 'tcp: #'name))
                   (ssl-tcp:name (syntax-prefix 'ssl-tcp: #'name)))
        (define (name url . args)
          (apply (if (ssl-tcp-scheme? url) ssl-tcp:name tcp:name)
                 url args)))))))

(define (ssl-tcp-scheme? url)
  (equal? "https" (url-scheme url)))

Posted on the users mailing list.