41 Contracts for macro subexpressions

▼ |  | Unstable

1 | Guidelines for developing unstable libraries
2 | Bytes
3 | Classes and Objects
4 | Contracts
5 | Definitions
6 | Dictionaries
7 | Directories
8 | Exceptions
9 | Filesystem
10 | Functions
11 | Lists
12 | Net
13 | Path
14 | PLane T Packages
15 | Ports
16 | Pretty-Printing
17 | Regular Expressions
18 | Requiring Modules
19 | Sandboxed Evaluation
20 | Scribble Documentation
21 | Sets
22 | S-Expression Diff
23 | Source Locations
24 | Strings
25 | Structs
26 | Syntax
27 | Planet Package Macros
28 | Text Representations
29 | Multiple Values
30 | XML and CSS
31 | Polymorphic Contracts
32 | Finding Mutated Variables
33 | Find
34 | Interface-Oriented Programming for Classes
35 | Sequences
36 | Hash Tables
37 | Match
38 | Generics
39 | Mark Parameters
40 | Debugging
41 | Contracts for macro subexpressions
42 | GUI libraries

On this page:

wrap-expr/ c

Version: 5.0.1.5
top← prev up next →

### 41`` Contracts for macro subexpressions

Ryan Culpepper <ryanc@racket-lang.org>

This library provides a procedure wrap-expr/c for applying contracts to macro subexpressions.

( require unstable/wrapc)

This library is unstable; compatibility will not be maintained. See Unstable for more information.

( wrap-expr/c |  | contract-expr |  |  |  |
|  | expr |  |  |  |
| [ | #:positive pos-blame |  |  |  |
|  | #:negative neg-blame |  |  |  |
|  | #:name expr-name |  |  |  |
|  | #:macro macro-name |  |  |  |
|  | #:context context]) |  | → |  | syntax?

contract-expr : syntax?
expr : syntax?

pos-blame

:

( or/c syntax? string? module-path-index?
'from-macro 'use-site 'unknown)

|  |  | = |  | 'use-site

neg-blame

:

( or/c syntax? string? module-path-index?
'from-macro 'use-site 'unknown)

|  |  | = |  | 'from-macro

expr-name : ( or/c identifier? symbol? string? #f) = #f
macro-name : ( or/c identifier? symbol? string? #f) = #f
context : ( or/c syntax? #f) = ( current-syntax-context)

Returns a syntax object representing an expression that applies the contract represented by contract-expr to the value produced by expr.

The contract’s positive blame represents the obligations of the expression being wrapped. The negative blame represents the obligations of the macro imposing the contract – the ultimate caller of wrap-expr/c. By default, the positive blame is taken as the module currently being expanded, and the negative blame is inferred from the definition site of the macro (itself inferred from the context argument). But both blame locations can be overridden.

Positive and negative blame locations are determined from pos-blame and neg-blame, respectively, as follows:

- If the argument is a string, it is used directly as the blame label.

- If the argument is syntax, its source location is used to produce the blame label.

- If the argument is a module path index, its resolved module path is used.

- If the argument is 'from-macro, the macro is inferred from either the macro-name argument (if macro-name is an identifier) or the context argument, and the module where it is defined is used as the negative blame location. If neither an identifier macro-name nor a context argument is given, the location is "unknown".

- If the argument is 'same-as-use-site, the module being expanded is used.

- If the argument is 'unknown, the blame label is "unknown".

The macro-name argument is used to determine the macro’s binding, if it is an identifier. If expr-name is given, macro-name is also included in the contract error message. If macro-name is omitted or #f, but context is a syntax object, then macro-name is determined from context.

If expr-name is not #f, it is used in the contract’s error message to describe the expression the contract is applied to.

The context argument is used, when necessary, to infer the macro name for the negative blame party and the contract error message. The context should be either an identifier or a syntax pair with an identifer in operator position; in either case, that identifier is taken as the macro ultimately requesting the contract wrapping.

Examples:

> ( define-syntax (myparameterize1 stx)
( syntax-case stx ()
[(_ ((p v)) body)
( with-syntax ([cp ( wrap-expr/c
#' parameter? #'p
#:name "the parameter argument"
#:context stx)])
#'( parameterize ((cp v)) body))]))

> (myparameterize1 (( current-input-port
( open-input-string "(1 2 3)")))
( read))

'(1 2 3)

> (myparameterize1 (('whoops 'something))
'whatever)

eval:4.0: top-level broke the contract parameter? on
the parameter argument of myparameterize1
; expected <parameter?>, given: 'whoops

> ( module mod racket
( require ( for-syntax unstable/wrapc))
( define-syntax (app stx)
( syntax-case stx ()
[(app f arg)
( with-syntax ([cf ( wrap-expr/c
#'(-> number? number?)
#'f
#:name "the function argument"
#:context stx)])
#'(cf arg))]))
( provide app))

> ( require 'mod)
> (app add1 5)
6
> (app add1 'apple)
eval:8.0: (quote mod) broke the contract (-> number?
number?) on the function argument of app given to
top-level; expected <number?>, given: 'apple
> (app ( lambda (x) 'pear) 5)
eval:9.0: top-level broke the contract (-> number? number?)
on the function argument of app; expected <number?>, given:
'pear

top← prev up next →