type-expander.hl.rkt (81809B)
1 #lang hyper-literate racket/base #:no-require-lang 2 @; The #:no-require-lang above is needed because type-expander requires 3 @; from 'main some identifiers (e.g. λ) which conflict with the re-required 4 @; racket/base. With this option, we loose arrows in DrRacket for the 5 @; built-ins in this file, and have otherwise no adverse effects. 6 @(require scribble-enhanced/doc) 7 @doc-lib-setup 8 9 @(module orig-ids racket/base 10 (require scribble/manual 11 (for-label typed/racket/base)) 12 (provide (all-defined-out)) 13 (define orig:: (racket :)) 14 (define orig:let (racket let)) 15 (define orig:→AnyBoolean:Integer (racket (→ Any Boolean : Integer)))) 16 @(require 'orig-ids) 17 18 @(unless-preexpanding 19 (require racket/require 20 (for-label (submod "..") 21 (only-in (submod ".." main) colon) 22 (subtract-in typed/racket/base (submod "..")) 23 (subtract-in racket typed/racket/base (submod "..")) 24 racket/require-syntax 25 racket/provide-syntax 26 typed/racket/unsafe 27 racket/format 28 racket/syntax 29 syntax/stx 30 syntax/parse 31 syntax/parse/experimental/template 32 syntax/id-table 33 auto-syntax-e 34 #;(subtract-in typed-racket/base-env/annotate-classes 35 (submod ".."))))) 36 37 @title[#:style manual-doc-style 38 #:tag "ty-xp-impl" 39 #:tag-prefix "type-expander/ty-xp-impl" 40 ]{Implementation of the type expander library} 41 42 @(chunks-toc-prefix 43 '("(lib type-expander/scribblings/type-expander-implementation.scrbl)" 44 "type-expander/ty-xp-impl")) 45 46 This document describes the implementation of the 47 @racketmodname[type-expander] library, using literate 48 programming. For the library's documentation, see the 49 @other-doc['(lib "type-expander/scribblings/type-expander.scrbl")] 50 document instead. 51 52 @section{Introduction} 53 54 Extensible types would be a nice feature for typed/racket. Unlike 55 @racket[require] and @racket[provide], which come with 56 @tc[define-require-syntax] and @tc[define-provide-syntax], and unlike 57 @tc[match], which comes with @tc[define-match-expander], @tc[typed/racket] 58 doesn't provide a way to define type expanders. The 59 @racketmodname[type-expander] library extends @racketmodname[typed/racket] 60 with the ability to define type expanders, i.e. type-level macros. 61 62 The @secref["ty-xp-more" #:tag-prefixes '("type-expander/ty-xp-more")] section 63 presents a small library of type expanders built upon the mechanism implemented 64 here. 65 66 We redefine the forms @tc[:], @tc[define], @tc[lambda] and so on to 67 equivalents that support type expanders. Type expanders are defined via the 68 @tc[define-type-expander] macro. Ideally, this would be handled directly by 69 @tc[typed/racket], which would directly expand uses of type expanders. 70 71 @(table-of-contents) 72 73 @section{Expansion model for type expanders} 74 75 Type expanders are expanded similarly to macros, with two minor differences: 76 @itemlist[ 77 @item{A form whose first element is a type expander, e.g. 78 @racket[(F . args₁)], can expand to the identifier of another type expander 79 @racket[G]. If the form itself appears as the first element of an outer form, 80 e.g. @racket[((F . args₁) . args₂)], the first expansion step will result in 81 @racket[(G . args₂)]. The official macro expander for Racket would then expand 82 @racket[G] on its own, as an 83 @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier macro}, without 84 passing the @racket[args₂] to it. In contrast, the type expander will expand 85 the whole @racket[(G . args₂)] form, letting @racket[G] manipulate the 86 @racket[args₂] arguments.} 87 @item{It is possible to write anonymous macros, 88 89 The @racket[Λ] form can be used to create anonymous type expanders. Anonymous 90 type expanders are to type expanders what anonymous functions are to function 91 definitions. The following table presents the expression-level and type-level 92 function and macro forms. Note that @racket[Let] serves as a type-level 93 equivalent to both @racket[let] and @racket[let-syntax], as anonymous macros 94 can be used in conjunction with @racket[Let] to obtain the equivalent of 95 @racket[let-syntax]. 96 97 @tabular[#:style 'boxed 98 #:sep (hspace 1) 99 #:column-properties '((right-border right) left) 100 #:row-properties '((bottom-border baseline) (baseline)) 101 (list (list "" 102 @bold{Definitions} 103 @bold{Local binding} 104 @bold{Anonymous functions}) 105 (list @bold{Functions} 106 @racket[define] 107 @racket[let] 108 @racket[λ]) 109 (list @bold{Macros} 110 @racket[define-syntax] 111 @racket[let-syntax] 112 @emph{N/A}) 113 (list @bold{Type‑level functions@superscript{a}} 114 @racket[define-type] 115 @racket[Let] 116 @racket[∀]) 117 (list @bold{Type‑level macros} 118 @racket[define-type-expander] 119 @racket[Let] 120 @racket[Λ]))] 121 122 @superscript{a}: The type-level functions are simple substitution functions, 123 and cannot perform any kind of computation. They are, in a sense, closer to 124 pattern macros defined with @racket[define-syntax-rule] than to actual 125 functions.}] 126 127 Combined, these features allow some form of "curried" application of type 128 expanders: The @racket[F] type expander could expand to an anonymous 129 @racket[Λ] type expander which captures the @racket[args₁] arguments. In the 130 second expansion step, the @racket[Λ] anonymous type expander would then 131 consume the @racket[args₂] arguments, allowing @racket[F] to effectively 132 rewrite the two nested forms, instead of being constrained to the innermost 133 form. 134 135 @subsection{Comparison with TeX's macro expansion model} 136 137 For long-time TeX or LaTeX users, this may raise some concerns. TeX programs 138 are parsed as a stream of tokens. A TeX commands is a macro. When a TeX macro 139 occurs in the stream of tokens, it takes its arguments by consuming a certain 140 number of tokens following it. After consuming these arguments, a TeX macro 141 may expand to another TeX macro, which in turn consumes more arguments. This 142 feature is commonly used in TeX to implement macros which consume a variable 143 number arguments: the macro will initially consume a single argument. 144 Depending on the value of that argument, it will then expand to a macro taking 145 @racket[_n] arguments, or another macro taking @racket[_m] arguments. This 146 pattern, omnipresent in any sufficiently large TeX program, opens the door to 147 an undesirable class of bugs: when a TeX macro invocation appears in the 148 source code, it is not clear syntactically how many arguments it will 149 eventually consume. An incorrect parameter value can easily cause it to 150 consume more arguments than expected. This makes it possible for the macro to 151 consume the end markers of surrounding environments, for example in the code: 152 153 @verbatim|{ 154 \begin{someEnvironment} 155 \someMacro{arg1}{arg2} 156 \end{someEnvironment} 157 }| 158 159 the @literal|{someMacro}| command may actually expect three arguments, in 160 which case it will consume the @literal|{\end}| token, but leave the 161 @literal|{{someEnvironment}}| token in the stream. This will result in a badly 162 broken TeX program, which will most likely throw an error complaining that the 163 environment @literal|{\begin{someEnvironment}}| is not properly closed. The 164 error may however occur in a completely different location, and may easily 165 cause a cascade of errors (the missing @literal|{\end{someEnvironment}}| may 166 cause later TeX commands to be interpreted in a different way, causing them to 167 misinterpret their arguments, which in turn may cause further errors. The end 168 result is a series of mysterious error messages somewhat unrelated to the 169 initial problem. 170 171 This problem with TeX macros can be summed up as follows: the number of tokens 172 following a TeX macro invocation that will be consumed by the macro is 173 unbounded, and cannot be easily guessed by looking at the raw source code, 174 despite the presence of programmer-friendly looking syntactic hints, like 175 wrapping arguments with @literal|{{…}}|. 176 177 We argue that the expansion model for type expanders is less prone to this 178 class of problems, for several reasons: 179 @itemlist[ 180 @item{Firstly, macros can only consume outer forms if they appear as the 181 leftmost leaf of the outer form, i.e. while the @racket[F] macro in the 182 expression 183 184 @racketblock[((F . args₁) . args₂)] 185 186 may access the @racket[args₂] arguments, it will be constrained within the 187 @racket[(F . args₁)] in the following code: 188 189 @racketblock[(H leading-args₂ (F . args₁) . more-args₂)] 190 191 The first case occurs much more rarely than the second, so is less likely to 192 happen} 193 @item{Secondly, all TeX macros will consume an arbitrary number of arguments 194 in a linear fashion until the end of the enclosing group or a paragraph 195 separation. In contrast, most type expanders will consume all the arguments 196 within their enclosing application form, and no more. ``Curried'' type 197 expanders, which expand to a lone macro identifier, will likely only represent 198 a small subset of all type expanders. For comparison, consider the following 199 TeX code: 200 201 @verbatim|{\CommandOne{argA}\CommandTwo{argB}}| 202 203 The @literal|{\CommandOne}| TeX macro might consume zero, one, two three or 204 more arguments. If it consumes zero arguments, @literal|{{argA}}| will not be 205 interpreted as an argument, but instead will represent a scoped expression, 206 similar to @racket[(let () argA)]. If @literal|{\CommandOne}| consumes two or 207 more arguments, @literal|{\CommandTwo}| will be passed as an argument, 208 unevaluated, and may be discarded or applied to other arguments than the 209 seemingly obvious @literal|{{argB}}| argument. The TeX code above could 210 therefore be equivalent to any the following Racket programs: 211 212 @racketblock[ 213 (CommandOne) 214 (let () argA) 215 (CommandTwo) 216 (let () argB)] 217 218 @racketblock[ 219 (CommandOne argA) 220 (CommandTwo) 221 (let () argB)] 222 223 @racketblock[ 224 (CommandOne) 225 (let () argA) 226 (CommandTwo argB)] 227 228 @racketblock[ 229 (CommandOne argA) 230 (CommandTwo argB)] 231 232 @racketblock[ 233 (CommandOne argA CommandTwo) 234 (let () argB)] 235 236 @racketblock[ 237 (CommandOne argA CommandTwo argB)] 238 239 In contrast, the obvious interpretation at a first glance of the TeX program 240 would be written as follows in Racket: 241 242 @racketblock[ 243 (CommandOne argA) 244 (CommandTwo argB)] 245 246 If these appear as ``arguments'' of a larger expression, then their meaning 247 is unambiguous (unless the larger expression is itself a macro): 248 249 @racketblock[ 250 (+ (CommandOne argA) 251 (CommandTwo argB))] 252 253 If however the @racket[(CommandOne argA)] is the first element in its form, 254 then, if it is a curried macro, it may consume the the 255 @racket[(CommandTwo argB)] form too: 256 257 258 @racketblock[ 259 ((CommandOne argA) 260 (CommandTwo argB))] 261 262 As stated earlier, this case will likely be less common, and it is clearer 263 that the intent of the programmer to pass @racket[(CommandTwo argB)] as 264 arguments to the result of @racket[(CommandOne argA)], either as a macro 265 application or as a regular run-time function application.} 266 @item{Finally, Racket macros (and type expanders) usually perform a somewhat 267 thorough check of their arguments, using @racket[syntax-parse] or 268 @racket[syntax-case] patterns. Arguments to macros and type expanders which do 269 not have the correct shape will trigger an error early, thereby limiting the 270 risk of causing errors in cascade.}] 271 272 @subsection{Interactions between type expanders and scopes} 273 274 Our expansion model for type expanders therefore allows a type expander to 275 escape the scope in which it was defined before it is actually expanded. For 276 example, the following type: 277 278 @RACKETBLOCK[ 279 (Let ([A Number]) 280 ((Let ([F (Λ (self T) 281 #`(Pairof #,(datum->syntax #'self 'A) 282 T))]) 283 (Let ([A String]) 284 F)) 285 A))] 286 287 first expands to: 288 289 @RACKETBLOCK[ 290 (F 291 A)] 292 293 and then expands to: 294 295 @RACKETBLOCK[ 296 (Pairof String A)] 297 298 and finally expands to: 299 300 @RACKETBLOCK[ 301 (Pairof String A)] 302 303 Effectively, @racket[F] captures the scope where its name appears (inside all 304 three @racket[Let] forms), but is expanded in a different context (outside of 305 the two innermost @racket[Let] forms). 306 307 Using Matthew Flatt's notation to indicate the scopes present on an 308 identifier, we can more explicitly show the expansion steps: 309 310 @RACKETBLOCK[ 311 (Let ([A Number]) 312 ((Let ([F (Λ (self T) 313 #`(Pairof #,(datum->syntax #'self 'A) 314 T))]) 315 (Let ([A String]) 316 F)) 317 A))] 318 319 The first @racket[Let] form annotates the identifier it binds with a fresh 320 scope, numbered @racket[1] here, and adds this scope to all identifiers within 321 its body. It stores the binding in the @racket[(tl-redirections)] binding 322 table, as shown by the comment above the code 323 324 @RACKETBLOCK[ 325 (code:comment "A¹ := Number") 326 ((Let¹ ([F¹ (Λ¹ (self¹ T¹) 327 #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹) 328 T¹))]) 329 (Let¹ ([A¹ String¹]) 330 F¹)) 331 A¹)] 332 333 The second @racket[Let] form then binds the @racket[F] identifier, adding a 334 fresh scope as before: 335 336 @RACKETBLOCK[ 337 (code:comment "A¹ := Number") 338 (code:comment "F¹² := (Λ¹ (self¹ T¹)") 339 (code:comment " #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹)") 340 (code:comment " T¹))") 341 ((Let¹² ([A¹² String¹²]) 342 F¹²) 343 A¹)] 344 345 The third @racket[Let] form then binds @racket[A] within its body, leaving the 346 outer @racket[A] unchanged: 347 348 @RACKETBLOCK[ 349 (code:comment "A¹ := Number") 350 (code:comment "F¹² := (Λ¹ (self¹ T¹)") 351 (code:comment " #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹)") 352 (code:comment " T¹))") 353 (code:comment "A¹²³ := String¹²") 354 (F¹²³ 355 A¹)] 356 357 The @racket[F¹²³] macro is then expanded, passing as an argument the syntax 358 object @racket[#'(F¹²³ A¹)]. A fresh scope is added to the identifiers 359 generated by the macro, in order to enforce macro hygiene. The @racket[A¹] 360 identifier is passed as an input to the macro, so it is left unchanged, and 361 @racket[A¹²³] is derived from @racket[F¹²³], via @racket[datum->syntax], and 362 therefore has the same scopes (@racket[F¹²³] is also a macro input, so it is 363 not tagged with the fresh scope). The @racket[Pairof¹] identifier, generated by 364 the macro, is however flagged with the fresh scope @racket[4]. The result of 365 the application of @racket[F] to this syntax object is: 366 367 @RACKETBLOCK[ 368 (code:comment "A¹ := Number") 369 (code:comment "F¹² := (Λ¹ (self¹ T¹)") 370 (code:comment " #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹)") 371 (code:comment " T¹))") 372 (code:comment "A¹²³ := String¹²") 373 (Pairof¹⁴ A¹²³ A¹)] 374 375 The @racket[Pairof¹⁴] type is resolved to the primitive type constructor 376 @racket[Pairof]: 377 378 @RACKETBLOCK[ 379 (code:comment "A¹ := Number") 380 (code:comment "F¹² := (Λ¹ (self¹ T¹)") 381 (code:comment " #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹)") 382 (code:comment " T¹))") 383 (code:comment "A¹²³ := String¹²") 384 (Pairof A¹²³ A¹)] 385 386 The type @racket[A¹²³] is then resolved to @racket[String¹²], which in turn is 387 resolved to the @racket[String] built-in type: 388 389 @RACKETBLOCK[ 390 (code:comment "A¹ := Number") 391 (code:comment "F¹² := (Λ¹ (self¹ T¹)") 392 (code:comment " #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹)") 393 (code:comment " T¹))") 394 (code:comment "A¹²³ := String¹²") 395 (Pairof String A¹)] 396 397 And the type @racket[A¹] is resolved to @racket[Number]: 398 399 @RACKETBLOCK[ 400 (code:comment "A¹ := Number") 401 (code:comment "F¹² := (Λ¹ (self¹ T¹)") 402 (code:comment " #`(Pairof¹ #,(datum->syntax¹ #'self¹ 'A¹)") 403 (code:comment " T¹))") 404 (code:comment "A¹²³ := String¹²") 405 (Pairof String Number)] 406 407 The @racket[syntax-local-value] function does not support querying the 408 transformer binding of identifiers outside of the lexical scope in which they 409 are bound. In our case, however, we need to access the transformer binding of 410 @racket[F¹²³] outside of the scope of the @racket[Let] binding it, and 411 similarly for @racket[A¹²³]. 412 413 @section{The @racket[prop:type-expander] structure type property} 414 415 Type expanders are identified by the @tc[prop:type-expander] 416 @tech[#:doc '(lib "scribblings/reference/reference.scrbl")]{structure type 417 property}. Structure type properties allow the same identifier to act as a 418 rename transformer, a match expander and a type expander, for example. Such an 419 identifier would have to implement the @tc[prop:rename-transformer], 420 @tc[prop:match-expander] and @tc[prop:type-expander] properties, respectively. 421 422 @chunk[<prop:type-expander> 423 (define-values (prop:type-expander 424 has-prop:type-expander? 425 get-prop:type-expander-value) 426 (make-struct-type-property 'type-expander prop-guard))] 427 428 The value of the @tc[prop:type-expander] property should either be a 429 transformer procedure of one or two arguments which will be called when 430 expanding the type, or the index of a field containing such a procedure. 431 432 @chunk[<prop-guard> 433 (define (prop-guard val struct-type-info-list) 434 (cond <prop-guard-field-index> 435 <prop-guard-procedure> 436 <prop-guard-else-error>))] 437 438 If the value is a field index, it should be within bounds. The 439 @tc[make-struct-field-accessor] function performs this check, and also returns 440 an accessor. The accessor expects an instance of the struct, and returns the 441 field's value. 442 443 @chunk[<prop-guard-field-index> 444 [(exact-nonnegative-integer? val) 445 (let* ([make-struct-accessor (cadddr struct-type-info-list)] 446 [accessor (make-struct-field-accessor make-struct-accessor val)]) 447 (λ (instance) 448 (let ([type-expander (accessor instance)]) 449 <prop-guard-field-value>)))]] 450 451 The expander procedure will take one argument: the piece of syntax 452 corresponding to the use of the expander. If the property's value is a 453 procedure, we therefore check that its arity includes 1. 454 455 @chunk[<prop-guard-field-value> 456 (cond 457 [(and (procedure? type-expander) 458 (arity-includes? (procedure-arity type-expander) 2)) 459 (curry type-expander instance)] 460 [(and (procedure? type-expander) 461 (arity-includes? (procedure-arity type-expander) 1)) 462 type-expander] 463 [else 464 (raise-argument-error 'prop:type-expander-guard 465 (~a "the value of the " val "-th field should" 466 " be a procedure whose arity includes 1 or" 467 " 2") 468 type-expander)])] 469 470 In the first case, when the property value is a field index, we return an 471 accessor function. The accessor function expects a struct instance, performs 472 some checks and returns the actual type expander procedure. 473 474 When the property's value is directly a type expander procedure, we follow the 475 same convention. We therefore return a function which, given a struct 476 instance, returns the type expander procedure (ignoring the @racket[_] 477 argument). 478 479 @chunk[<prop-guard-procedure> 480 [(procedure? val) 481 (cond 482 [(arity-includes? (procedure-arity val) 2) 483 (λ (s) (curry val s))] 484 [(arity-includes? (procedure-arity val) 1) 485 (λ (_) val)] 486 [else 487 (raise-argument-error 'prop:type-expander-guard 488 "a procedure whose arity includes 1 or 2" 489 val)])]] 490 491 When the value of the @racket[prop:type-expander] property is neither a 492 positive field index nor a procedure, an error is raised: 493 494 @chunk[<prop-guard-else-error> 495 [else 496 (raise-argument-error 497 'prop:type-expander-guard 498 (~a "a procedure whose arity includes 1 or 2, or an exact " 499 "non-negative integer designating a field index within " 500 "the structure that should contain a procedure whose " 501 "arity includes 1 or 2.") 502 val)]] 503 504 @subsection{The @racket[type-expander] struct} 505 506 We make a simple struct that implements @tc[prop:type-expander] and nothing 507 else. It has a single field, @racket[expander-proc], which contains the type 508 expander transformer procedure. 509 510 @chunk[<type-expander-struct> 511 (struct type-expander (expander-proc) #:transparent 512 #:extra-constructor-name make-type-expander 513 #:property prop:type-expander (struct-field-index expander-proc))] 514 515 @section{Associating type expanders to identifiers} 516 517 @subsection{The @racket[type-expander] syntax class} 518 519 The @tc[type-expander] syntax class recognises identifiers 520 which are bound to type expanders. These fall into three cases: 521 @itemlist[ 522 @item{The identifier's @racket[syntax-local-value] is an instance of a struct 523 implementing @racket[prop:type-expander]} 524 @item{The identifier has been bound by a type-level local binding form like 525 @racket[Let] or @racket[∀], and therefore are registered in the 526 @racket[(tl-redirections)] binding table.} 527 @item{The identifier has been patched via @racket[patch-type-expander], i.e. 528 a type expander has been globally attached to an existing identifier, in which 529 case the type expander is stored within the @racket[patched] free identifier 530 table.}] 531 532 @chunk[<expand-type-syntax-classes> 533 (define-syntax-class type-expander 534 (pattern local-expander:id 535 #:when (let ([b (binding-table-find-best (tl-redirections) 536 #'local-expander 537 #f)]) 538 (and b (has-prop:type-expander? b))) 539 #:with code #'local-expander) 540 (pattern (~var expander 541 (static has-prop:type-expander? "a type expander")) 542 #:when (not (binding-table-find-best (tl-redirections) 543 #'expander 544 #f)) 545 #:with code #'expander) 546 (pattern patched-expander:id 547 #:when (let ([p (free-id-table-ref patched 548 #'patched-expander 549 #f)]) 550 (and p (has-prop:type-expander? p))) 551 #:when (not (binding-table-find-best (tl-redirections) 552 #'expander 553 #f)) 554 #:with code #'patched-expander))] 555 556 We also define a syntax class which matches types. Since types can bear many 557 complex cases, and can call type expanders which may accept arbitrary syntax, 558 we simply define the @tc[type] syntax class as @tc[expr]. Invalid syntax will 559 be eventually caught while expanding the type, and doing a thorough check 560 before any processing would only make the type expander slower, with little 561 actual benefits. The @tc[type] syntax class is however used in syntax patterns 562 as a form of documentation, to clarify the distinction between types and 563 run-time or compile-time expressions. 564 565 @CHUNK[<type-syntax-class> 566 (define-syntax-class type 567 (pattern :expr))] 568 569 @chunk[<type-contract> 570 (define stx-type/c syntax?)] 571 572 Finally, we define a convenience syntax class which expands the matched type: 573 574 @chunk[<type-expand-syntax-class> 575 (define-syntax-class type-expand! 576 #:attributes (expanded) 577 (pattern t:expr 578 #:with expanded (expand-type #'t #f)))] 579 580 @subsection{Calling type expanders} 581 582 The @tc[apply-type-expander] function applies the syntax expander transformer 583 function associated to @tc[type-expander-id]. It passes @tc[stx] as the single 584 argument to the transformer function. Usually, @tc[stx] will be the syntax 585 used to call the type expander, like @tc[#'(te arg ...)] or just @tc[#'te] if 586 the type expander is not in the first position of a form. 587 588 The identifier @tc[type-expander-id] should be bound to a type expander, in 589 one of the three possible ways described above. 590 591 @chunk[<apply-type-expander> 592 (define/contract (apply-type-expander type-expander-id stx) 593 (-> identifier? syntax? syntax?) 594 (let ([val (or (binding-table-find-best (tl-redirections) 595 type-expander-id 596 #f) 597 (let ([slv (syntax-local-value type-expander-id 598 (λ () #f))]) 599 (and (has-prop:type-expander? slv) slv)) 600 (free-id-table-ref patched type-expander-id #f))] 601 [ctxx (make-syntax-introducer)]) 602 <apply-type-expander-checks> 603 (ctxx (((get-prop:type-expander-value val) val) (ctxx stx)))))] 604 605 The @racket[apply-type-expander] function checks that its 606 @racket[type-expander-id] argument is indeed a type expander before attempting 607 to apply it: 608 609 @chunk[<apply-type-expander-checks> 610 (unless val 611 (raise-syntax-error 'apply-type-expander 612 (format "Can't apply ~a, it is not a type expander" 613 type-expander-id) 614 stx 615 type-expander-id))] 616 617 @subsection{Associating type expanders to already existing identifiers} 618 619 As explained above, existing identifiers which are provided by other libraries 620 can be ``patched'' so that they behave like type expanders, using a global 621 table associating existing identifiers to the corresponding expander code: 622 623 @chunk[<patched> 624 (define patched (make-free-id-table))] 625 626 @CHUNK[<patch> 627 (define-syntax patch-type-expander 628 (syntax-parser 629 [(_ id:id expander-expr:expr) 630 #`(begin 631 (begin-for-syntax 632 (free-id-table-set! patched 633 #'id 634 (type-expander #,(syntax/loc this-syntax 635 expander-expr)))))]))] 636 637 @subsection{Defining new type expanders} 638 639 The @tc[define-type-expander] macro binds @tc[_name] to a 640 type expander which uses @tc[(λ (_arg) . _body)] as the 641 transformer procedure. To achieve this, we create a 642 transformer binding (with @tc[define-syntax]), from 643 @tc[_name] to an instance of the @tc[type-expander] 644 structure. 645 646 @CHUNK[<define-type-expander> 647 (define-syntax define-type-expander 648 (syntax-parser 649 [(_ (name:id arg:id) . body) 650 #`(define-syntax name 651 (type-expander #,(syntax/loc this-syntax (λ (arg) . body))))] 652 [(_ name:id fn:expr) 653 #`(define-syntax name 654 (type-expander #,(syntax/loc this-syntax fn)))]))] 655 656 @subsection[#:tag "shadow"]{Locally binding type expanders} 657 658 Some features of the type expander need to locally bind new type expanders: 659 660 @itemlist[ 661 @item{The @racket[(Let ([_id _expr] …) . _body)] special form binds the 662 identifiers @racket[_id …] to the type expanders @racket[_expr …] in its 663 @racket[_body].} 664 @item{When expanding the body of a @racket[(∀ (Tᵢ …) body)] form, the 665 @racket[Tᵢ] bound by the @racket[∀] may shadow some type expanders with the 666 same name. If the @racket[∀] form is directly applied to arguments, each 667 @racket[Tᵢ] is instead bound to the corresponding argument.} 668 @item{When expanding the body of a @racket[(Rec T body)] form, the @racket[T] 669 bound by the @racket[Rec] may shadow a type expander with the same name.}] 670 671 We use @racket[with-bindings] (defined in another file) to achieve this. The 672 code 673 674 @racketblock[(with-bindings [_bound-ids _transformer-values] 675 _rebind-stx 676 _transformer-body)] 677 678 evaluates @racket[_transformer-body] in the transformer environment. It 679 creates a fresh scope, which it applies to the @racket[_bound-ids] and the 680 @racket[_rebind-stx]. It associates each modified @racket[_bound-id] with the 681 corresponding @racket[_transformer-value] in the @racket[(tl-redirections)] 682 binding table. The @racket[with-bindings] form does not mutate the syntax 683 objects, instead it shadows the syntax pattern variables mentioned in 684 @racket[_bound-ids] and @racket[_rebind-stx] with versions pointing to the 685 same syntax objects, but with the fresh scope flipped on them. 686 687 The code 688 689 @racketblock[(with-rec-bindings [_bound-ids _generate-transformer-values _rhs] 690 _rebind-stx 691 _transformer-body)] 692 693 works in the same way, but it also flips the fresh scope on each element of 694 @racket[_rhs]. The @racket[_generate-transformer-values] is expected to be a 695 transformer expression which, given an element of @racket[_rhs] with the 696 flipped scope, produces the transformer value to bind to the corresponding 697 @racket[_bound-id]. 698 699 700 The implementation of @racket[with-bindings] unfortunately does not play well 701 with @racket[syntax-local-value], so the binding table has to be queried 702 directly instead of using @racket[syntax-local-value]. To our knowledge, the 703 only ways to make new bindings recognised by @racket[syntax-local-value] are: 704 @itemlist[ 705 @item{To expand to a @racket[define-syntax] form, followed with a macro 706 performing the remaining work} 707 @item{Equivalently, to expand to a @racket[let-syntax] form, whose body is a 708 macro performing the remaining work} 709 @item{To call @racket[local-expand] with an internal definition context which 710 contains the desired bindings} 711 @item{To explicitly call @racket[syntax-local-value] with an internal 712 definition context argument}] 713 714 It is not practical in our case to use the first solution involving 715 @racket[define-syntax], as the type expander may be called while expanding an 716 expression (e.g. @racket[ann]). The next two solutions assume that 717 @racket[syntax-local-value] will be called in a well-scoped fashion (in the 718 sense of the official expander): in the second solution, 719 @racket[syntax-local-value] must be called by expansion-time code located 720 within the scope of the @racket[let-syntax] form, and in the third solution, 721 @racket[syntax-local-value] must be called within the dynamic extent of 722 @racket[local-expand]. The last solution works, but requires that the user 723 explicitly passes the appropriate internal definition context. 724 725 The second and third solutions cannot be applied in our case, because type 726 expanders can be expanded outside of the scope in which they were defined and 727 used, as explained the 728 @secref["Interactions_between_type_expanders_and_scopes"] section. 729 730 The current version of the type expander does not support a reliable 731 alternative to @racket[syntax-local-value] which takes into account local 732 binding forms for types (@racket[Let], @racket[∀] and @racket[Rec]), but one 733 could be implemented, either by using some tricks to make the first solution 734 work, or by providing an equivalent to @racket[syntax-local-value] which 735 consults the @racket[(tl-redirections)] binding table. 736 737 @section{Expanding types} 738 739 The @tc[expand-type] function fully expands the type 740 @tc[stx]. As explained in 741 @secref["shadow"], shadowing would be better handled using 742 scopes. The @tc[expand-type] function starts by defining 743 some syntax classes, then parses @tc[stx], which can fall in 744 many different cases. 745 746 @CHUNK[<expand-type> 747 (define (expand-type stx [applicable? #f]) 748 (start-tl-redirections 749 <expand-type-syntax-classes> 750 (define (expand-type-process stx first-pass?) 751 <expand-type-debug-before> 752 ((λ (result) <expand-type-debug-after>) 753 (parameterize (<expand-type-debug-indent>) 754 <expand-type-debug-rules> 755 (syntax-parse stx 756 <expand-type-case-:> 757 <expand-type-case-expander> 758 <expand-type-case-∀-later> 759 <expand-type-case-Λ-later> 760 <expand-type-case-app-expander> 761 <expand-type-case-∀-through> 762 <expand-type-case-Rec> 763 <expand-type-case-app-Λ> 764 <expand-type-case-just-Λ/not-applicable> 765 <expand-type-case-∀-app> 766 <expand-type-case-Let> 767 <expand-type-case-Letrec> 768 <expand-type-case-noexpand> 769 770 (code:comment "Must be after other special application cases") 771 <expand-type-case-app-other> 772 <expand-type-case-app-fallback> 773 <expand-type-case-fallback-T>)))) 774 (expand-type-process stx #t)))] 775 776 @subsection{Cases handled by @racket[expand-type]} 777 778 The cases described below which expand a use of a type expander re-expand the 779 result, by calling @tc[expand-type] once more. This process is repeated until 780 no more expansion can be performed. This allows type expanders to produce 781 calls to other type expanders, exactly like macros can produce calls to other 782 macros. 783 784 We distinguish the expansion of types which will appear as the first element 785 of their parent form from types which will appear in other places. When the 786 @racket[applicable?] argument to @racket[expand-type] is @racket[#true], it 787 indicates that the current type, once expanded, will occur as the first 788 element of its enclosing form. If the expanded type is the name of a type 789 expander, or a @racket[∀] or @racket[Λ] form, it will be directly applied to 790 the given arguments by the type expander. When @racket[applicable?] is 791 @racket[#false], it indicates that the current type, once expanded, will 792 @emph{not} appear as the first element of its enclosing form (it will appear 793 in another position, or it is at the top of the syntax tree representing the 794 type). 795 796 When @racket[applicable?] is @racket[#true], if the type is the name of a type 797 expander, or a @racket[∀] or @racket[Λ] form, it is not expanded immediately. 798 Instead, the outer form will expand it with the arguments. Otherwise, these 799 forms are expanded without arguments, like 800 @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier macros} would be. 801 802 @subsection{Applying type expanders} 803 804 When a type expander is found in a non-applicable position, it is called, 805 passing the identifier itself to the expander. An 806 @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier macro} would be 807 called in the same way. 808 809 @CHUNK[<expand-type-case-expander> 810 [expander:type-expander 811 #:when (not applicable?) 812 (rule id-expander/not-applicable 813 (let ([ctxx (make-syntax-introducer)]) 814 (expand-type (ctxx (apply-type-expander #'expander.code 815 (ctxx #'expander))) 816 applicable?)))]] 817 818 When a type expander is found in an applicable position, it is returned 819 without modification, so that the containing application form may expand it 820 with arguments. When the expander @racket[e] appears as @racket[(e . args)], 821 it is applicable. It is also applicable when it appears as 822 @racket[((Let (bindings…) e) . args)], for example, because @racket[Let] 823 propagates its @racket[applicable?] status. 824 825 @CHUNK[<expand-type-case-expander> 826 [expander:type-expander 827 #:when applicable? 828 (rule id-expander/applicable 829 #'expander)]] 830 831 When a form contains a type expander in its first element, the type expander 832 is called. The result is re-expanded, so that a type expander can expand to a 833 use of another type expander. 834 835 @CHUNK[<expand-type-case-app-expander> 836 [(~and expander-call-stx (expander:type-expander . _)) 837 (rule app-expander 838 (let ([ctxx (make-syntax-introducer)]) 839 (expand-type (ctxx (apply-type-expander #'expander.code 840 (ctxx #'expander-call-stx))) 841 applicable?)))]] 842 843 When a form of the shape @racket[(_f . _args)] is encountered, and the 844 @racket[_f] element is not a type expander, the @racket[_f] form is expanded, 845 and the whole form (with @racket[_f] replaced by its expansion) is expanded a 846 second time. The @racket[applicable?] parameter is set to @racket[#true] while 847 expanding @racket[_f], so that if @racket[_f] produces a type expander (e.g. 848 @racket[_f] has the shape @racket[(Let (…) _some-type-expander)]), the type 849 expander can be applied to the @racket[_args] arguments. 850 851 @CHUNK[<expand-type-case-app-other> 852 [(~and whole (f . args)) 853 #:when first-pass? 854 (rule app-other 855 (expand-type-process 856 (datum->syntax #'whole 857 (cons (expand-type #'f #true) #'args) 858 #'whole 859 #'whole) 860 #f))]] 861 862 @subsubsection{Polymorphic types with @racket[∀]} 863 864 When the @tc[∀] or @tc[All] special forms from @racketmodname[typed/racket] 865 are used, the bound type variables may shadow some type expanders. The type 866 expanders used in the body @tc[T] which have the same identifier as a bound 867 variable will be affected by this (they will not act as a type-expander 868 anymore). The body of the @tc[∀] or @tc[All] form is expanded with the 869 modified environment. The result is wrapped again with 870 @tc[(∀ (TVar …) expanded-T)], in order to conserve the behaviour from 871 @racketmodname[typed/racket]'s @tc[∀]. 872 873 @CHUNK[<expand-type-case-∀-through> 874 [({~and ∀ {~literal ∀}} (tvar:id …) T:type) 875 #:when (not applicable?) 876 (rule just-∀/not-applicable 877 (with-syntax ([(tvar-vars-only …) (remove-ddd #'(tvar …))]) 878 (with-bindings [(tvar-vars-only …) (stx-map <shadowed> 879 #'(tvar-vars-only …))] 880 (T tvar …) 881 #`(∀ (tvar …) 882 #,(expand-type #'T #f)))))]] 883 884 Where @racket[<shadowed>] is used to bind the type variables @racket[tvarᵢ] to 885 @racket[(No-Expand tvarᵢ)], so that their occurrences are left intact by the 886 type expander: 887 888 @CHUNK[<shadowed> 889 (λ (__τ) 890 (make-type-expander 891 (λ (stx) 892 (syntax-case stx () 893 [self (identifier? #'self) #'(No-Expand self)] 894 [(self . args) #'((No-Expand self) . args)]))))] 895 896 When a @racket[∀] polymorphic type is found in an applicable position, it is 897 returned without modification, so that the containing application form may 898 expand it, binding the type parameters to their effective arguments. 899 900 @CHUNK[<expand-type-case-∀-later> 901 [(~and whole ({~literal ∀} (tvar:id …) T:type)) 902 #:when applicable? 903 (rule just-∀/applicable 904 #'whole)]] 905 906 When a @racket[∀] polymorphic type is immediately applied to arguments, the 907 type expander attempts to bind the type parameters to the effective arguments. 908 It currently lacks any support for types under ellipses, and therefore that 909 case is currently handled by the @racket[<expand-type-case-app-fallback>] case 910 described later. 911 912 @chunk[<expand-type-case-∀-app> 913 [(({~literal ∀} ({~and tvar:id {~not {~literal …}}} …) τ) arg …) 914 (unless (= (length (syntax->list #'(tvar …))) 915 (length (syntax->list #'(arg …)))) 916 <app-args-error>) 917 (rule app-∀ 918 (with-bindings [(tvar …) (stx-map (λ (a) (make-type-expander (λ (_) a))) 919 #'(arg …))] 920 τ 921 (expand-type #'τ applicable?)))]] 922 923 If the given number of arguments does not match the expected number of 924 arguments, an error is raised immediately: 925 926 @chunk[<app-args-error> 927 (raise-syntax-error 928 'type-expander 929 (format (string-append "Wrong number of arguments to " 930 "polymorphic type: ~a\n" 931 " expected: ~a\n" 932 " given: ~a" 933 " arguments were...:\n") 934 (syntax->datum #'f) 935 (length (syntax->list #'(tvar …))) 936 (length (syntax->list #'(arg …))) 937 (string-join 938 (stx-map (λ (a) 939 (format "~a" (syntax->datum a))) 940 #'(arg …)) 941 "\n")) 942 #'whole 943 #'∀ 944 (syntax->list #'(arg …)))] 945 946 @subsubsection{Recursive types with @racket[Rec]} 947 948 Similarly, the @tc[Rec] special form will cause the bound 949 variable @tc[R] to shadow type expanders with the same name, 950 within the extent of the body @tc[T]. The result is wrapped 951 again with @tc[(Rec R expanded-T)], in order to conserve the 952 behaviour from @racketmodname[typed/racket]'s @tc[Rec]. 953 954 @CHUNK[<expand-type-case-Rec> 955 [((~literal Rec) R:id T:type) 956 (rule Rec 957 #`(Rec R #,(with-bindings [R (<shadowed> #'R)] 958 T 959 (expand-type #'T #f))))]] 960 961 @subsubsection{Local bindings with @racket[Let] and @racket[Letrec]} 962 963 The @tc[Let] special form binds the given identifiers to the corresponding 964 type expanders. We use @racket[with-bindings], as explained above in 965 @secref["shadow" #:doc '(lib "type-expander/type-expander.hl.rkt")], to bind 966 the @racket[Vᵢ …] identifiers to their corresponding @racket[Eᵢ] while 967 expanding @racket[T]. 968 969 @CHUNK[<expand-type-case-Let> 970 [((~commit (~literal Let)) ([Vᵢ:id Eᵢ] …) T:type) 971 (rule Let 972 (with-bindings [(Vᵢ …) 973 (stx-map (λ (Eᵢ) 974 (make-type-expander 975 (λ (stx) 976 (syntax-case stx () 977 [self (identifier? #'self) Eᵢ] 978 [(self . argz) #`(#,Eᵢ . argz)])))) 979 #'(Eᵢ …))] 980 T 981 (expand-type #'T applicable?)))]] 982 983 The @tc[Letrec] special form behaves in a similar way, but uses 984 @racket[with-rec-bindings], so that the right-hand-side expressions 985 @racket[Eᵢ] appear to be within the scope of all the @racket[Vᵢ] bindings. 986 987 @CHUNK[<expand-type-case-Letrec> 988 [((~commit (~literal Letrec)) ([Vᵢ:id Eᵢ] …) T:type) 989 (rule Letrec 990 (with-rec-bindings [(Vᵢ …) 991 (λ (Eᵢ) 992 (make-type-expander 993 (λ (stx) 994 (syntax-case stx () 995 [self (identifier? #'self) Eᵢ] 996 [(self . args444) #`(#,Eᵢ . args444)])))) 997 Eᵢ] 998 T 999 (expand-type #'T applicable?)))]] 1000 1001 @subsubsection{Anonymous types with @racket[Λ]} 1002 1003 When an anonymous type expander appears as the first element of its enclosing 1004 form, it is applied to the given arguments. We use the 1005 @racket[trampoline-eval] function defined in another file, which evaluates the 1006 given quoted transformer expression, while limiting the issues related to 1007 scopes. The ``official'' @racket[eval] function from 1008 @racketmodname[racket/base] removes one of the module scopes which are 1009 normally present on the expression to evaluate. In our case, we are evaluating 1010 an anonymous type expander, i.e. a transformer function. When using 1011 @racket[eval], identifiers generated by the transformer function may not have 1012 the expected bindings. The alternative @racket[trampoline-eval] seems to solve 1013 this problem. 1014 1015 The @racket[auto-syntax-case] form is used, so that an anonymous type expander 1016 @racket[(Λ (_ a b) …)] can either use @racket[a] and @racket[b] as pattern 1017 variables in quoted syntax objects, or as regular values (i.e 1018 @racket[syntax->datum] is automatically applied on the syntax pattern 1019 variables when they are used outside of syntax templates, instead of throwing 1020 an error). 1021 1022 @chunk[<eval-anonymous-expander-code> 1023 (trampoline-eval 1024 #'(λ (stx) 1025 (define ctxx (make-syntax-introducer)) 1026 (ctxx (auto-syntax-case (ctxx (stx-cdr stx)) () 1027 [formals (let () . body)]))))] 1028 1029 This case works by locally binding a fresh identifier @racket[tmp] to a type 1030 expander, and then applying that type expander. It would also be possible to 1031 immediately invoke the type expander function. 1032 1033 @chunk[<expand-type-case-app-Λ> 1034 [{~and whole (({~literal Λ} formals . body) . __args)} 1035 ;; TODO: use the same code as for the not-applicable case, to avoid ≠ 1036 (rule app-Λ 1037 (with-syntax* ([tmp (gensym '#%Λ-app-)] 1038 [call-stx #'(tmp . whole)]) 1039 (with-bindings [tmp (make-type-expander 1040 <eval-anonymous-expander-code>)] 1041 call-stx 1042 (expand-type #'call-stx applicable?))))]] 1043 1044 When a @racket[Λ] anonymous type expander appears on its own, in a 1045 non-applicable position, it is expanded like an 1046 @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier macro} would 1047 be. 1048 1049 This case is implemented like the @racket[<expand-type-case-app-Λ>] case, i.e. 1050 by locally binding a fresh identifier @racket[tmp] to a type expander, and 1051 then applying that type expander. The difference is that in the 1052 @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier macro} case, 1053 the syntax object given as an argument to the type expander contains only the 1054 generated @racket[tmp] identifier. This allows the type expander to easily 1055 recognise the @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier 1056 macro} case, where the whole syntax form is an identifier, from regular 1057 applications, where the whole syntax form is a syntax pair. The whole original 1058 syntax is attached @racket[cons]ed onto a syntax property named 1059 @racket['original-Λ-syntax], in (unlikely) case the type expander needs to 1060 access the original @racket[Λ] syntax used to call it (this is an experimental 1061 feature, and may change without notice in later versions). 1062 1063 @CHUNK[<expand-type-case-just-Λ/not-applicable> 1064 [{~and whole ({~literal Λ} formals . body)} 1065 #:when (not applicable?) 1066 (rule just-Λ/not-applicable 1067 (with-syntax* ([tmp (syntax-property 1068 (datum->syntax #'whole 1069 (gensym '#%Λ-id-macro-) 1070 #'whole 1071 #'whole) 1072 'original-Λ-syntax 1073 (cons #'whole 1074 (or (syntax-property #'whole 1075 'original-Λ-syntax) 1076 null)))] 1077 [call-stx #'(tmp . tmp)]) 1078 (with-bindings [tmp (make-type-expander 1079 <eval-anonymous-expander-code>)] 1080 call-stx 1081 ;; applicable? should be #f here, otherwise it would have been 1082 ;; caught by other cases. 1083 (expand-type #'call-stx applicable?))))]] 1084 1085 When a @racket[Λ] anonymous type expander appears on its own, in an applicable 1086 position, it is returned without modification, so that the containing 1087 application form may expand it with arguments (instead of expanding it like an 1088 @tech[#:doc '(lib "scribblings/guide/guide.scrbl")]{identifier macro} would 1089 be). 1090 1091 @CHUNK[<expand-type-case-Λ-later> 1092 [(~and whole ({~literal Λ} formals . body)) 1093 #:when applicable? 1094 (rule just-Λ/applicable 1095 #'whole)]] 1096 1097 @subsubsection{Preventing the expansion of types with @racket[No-Expand]} 1098 1099 The @racket[No-Expand] special form prevents the type expander from 1100 re-expanding the result. This is useful for example for the implementation of 1101 the fancy @racket[quote] expander, which relies on the built-in @racket[quote] 1102 expander. It is also used to implement shadowing: type variables bound by 1103 @racket[∀] in non-applicable positions and type variables bound by 1104 @racket[Rec] are re-bound to type expanders returning 1105 @racket[(No-Expand original-tvar)]. 1106 1107 @CHUNK[<expand-type-case-noexpand> 1108 [((~literal No-Expand) T) 1109 (rule just-No-Expand 1110 #'T)] 1111 [(((~literal No-Expand) T) arg ...) 1112 (rule app-No-Expand 1113 #`(T #,@(stx-map (λ (τ) (expand-type τ #f)) #'(arg ...))))]] 1114 1115 @subsubsection{The overloaded @racket[:] identifier} 1116 1117 This case handles the colon identifiers @tc[:] (overloaded by this 1118 library) and @|orig::| (provided by @racketmodname[typed/racket]). Wherever 1119 the new overloaded @tc[:] identifier appears in a type, we want to convert it 1120 back to the original @orig:: from @racketmodname[typed/racket]. The goal is 1121 that a type of the form @racket[(→ Any Boolean : Integer)], using the new 1122 @tc[:], will get translated to @orig:→AnyBoolean:Integer, using the old 1123 @orig:: so that it gets properly interpreted by @racketmodname[typed/racket]'s 1124 parser. 1125 1126 @chunk[<expand-type-case-:> 1127 [(~and c (~literal new-:)) 1128 (rule (datum->syntax #'here ': #'c #'c) 1129 ':)]] 1130 1131 @subsubsection{Last resort cases: leaving the type unchanged} 1132 1133 If the type expression to expand was not matched by any of the above cases, 1134 then it can still be an application of a polymorphic type @tc[T]. The 1135 arguments @tc[TArg …] can contain uses of type expanders. We therefore expand 1136 each separately, and combine the results. 1137 1138 @CHUNK[<expand-type-case-app-fallback> 1139 [{~and whole (T TArg …)} 1140 (rule app-fallback 1141 (quasisyntax/loc #'whole 1142 (T #,@(stx-map (λ (a) (expand-type a #f)) #'(TArg ...)))))]] 1143 1144 As a last resort, we consider that the type @tc[T] (which 1145 would most likely be an identifier) is either a built-in 1146 type provided by @tc[typed/racket], or a user-declared type 1147 introduced by @tc[define-type]. In both cases, we just leave 1148 the type as-is. 1149 1150 @CHUNK[<expand-type-case-fallback-T> 1151 [T 1152 (rule just-fallback 1153 #'T)]] 1154 1155 @subsection{Debugging type expanders} 1156 1157 In order to facilitate writing type expanders, it is possible to print the 1158 inputs, steps and outputs of the expander using 1159 @racket[(debug-type-expander #t)], which sets the value of 1160 @racket[debug-type-expander?]. This can then be undone using 1161 @racket[(debug-type-expander #f)]. 1162 1163 @chunk[<expand-type-debug-outer> 1164 (define debug-type-expander? (box #f))] 1165 1166 @chunk[<debug-type-expander> 1167 (define-syntax (debug-type-expander stx) 1168 (syntax-case stx () 1169 [(_ #t) (set-box! debug-type-expander? #t) #'(void)] 1170 [(_ #f) (set-box! debug-type-expander? #f) #'(void)]))] 1171 1172 For better readability, each level of recursion indents the debugging 1173 information: 1174 1175 @chunk[<expand-type-debug-outer> 1176 (define indent (make-parameter 0))] 1177 1178 @chunk[<expand-type-debug-indent> 1179 [indent (+ (indent) 3)]] 1180 1181 Before expanding a term, it is printed: 1182 1183 @chunk[<expand-type-debug-before> 1184 (when (unbox debug-type-expander?) 1185 (printf "~a~a ~a" 1186 (make-string (indent) #\ ) 1187 applicable? 1188 (+scopes stx)))] 1189 1190 Once the term has been expanded, the original term and the expanded term are 1191 printed: 1192 1193 @chunk[<expand-type-debug-after> 1194 (when (unbox debug-type-expander?) 1195 (printf "~a~a ~a\n~a=> ~a (case: ~a)\n" 1196 (make-string (indent) #\ ) 1197 applicable? 1198 (+scopes stx) 1199 (make-string (indent) #\ ) 1200 (+scopes (car result)) 1201 (cdr result)) 1202 (when (= (indent) 0) 1203 (print-full-scopes))) 1204 (car result)] 1205 1206 Finally, each rule for the type expander is wrapped with the @racket[rule] 1207 macro, which prints the name of the rule, and returns a pair containing the 1208 result and the rule's name, so that the debugging information indicates the 1209 rule applied at each step. 1210 1211 @chunk[<expand-type-debug-rules> 1212 (define-syntax-rule (rule name e) 1213 (begin (when (unbox debug-type-expander?) 1214 (printf "(case:~a)\n" 1215 'name)) 1216 (cons e 'name)))] 1217 1218 @section{Overloading @racket[typed/racket] forms} 1219 1220 Throughout this section, we provide alternative definitions of the 1221 @tc[typed/racket] forms @tc[:], @tc[lambda], @tc[define], @tc[struct], @tc[ann], 1222 @tc[inst]… . We write these definitions with @tc[syntax-parse], using the syntax 1223 classes defined in section @secref{type-expander|syntax-classes}. 1224 1225 Most of the time, we will use the experimental @tc[template] macro from 1226 @tc[syntax/parse/experimental/template] which allows more concise code than the 1227 usual @code{#'()} and @code{#`()}. 1228 1229 @subsection[#:tag "type-expander|syntax-classes"]{syntax classes} 1230 1231 The syntax classes from 1232 @tc[typed-racket/base-env/annotate-classes] match against 1233 the @orig:: literal. Since we provide a new definition for 1234 it, these syntax classes do not match code using our 1235 definition of @tc[:]. We therefore cannot use the original 1236 implementations of @tc[curried-formals] and 1237 @tc[lambda-formals], and instead have to roll out our own 1238 versions. 1239 1240 We take that as an opportunity to expand the types directly from the syntax 1241 classes using @tc[#:with], instead of doing that inside the macros that use 1242 them. 1243 1244 The @tc[colon] syntax class records the identifier it matches as a "disappeared 1245 use", which means that DrRacket will draw an arrow from the library importing it 1246 (either @racketmodname[typed/racket] or @racketmodname[type-expander]) to the 1247 identifier. Unfortunately, this effect is not (yet) undone by 1248 @racketmodname[syntax/parse]'s backtracking. See 1249 @url{https://groups.google.com/forum/#!topic/racket-users/Nc1klmsj9ag} for more 1250 details about this. 1251 1252 @chunk[<remove-ddd> 1253 (define (remove-ddd stx) 1254 (remove #'(... ...) (syntax->list stx) free-identifier=?))] 1255 1256 @CHUNK[<syntax-classes> 1257 (define-syntax-class colon 1258 #:attributes () 1259 (pattern (~and {~or {~literal new-:} {~literal :}} 1260 C 1261 {~do (record-disappeared-uses (list #'C))}))) 1262 1263 (define-splicing-syntax-class new-maybe-kw-type-vars 1264 #:attributes ([vars 1] maybe) 1265 (pattern kw+vars:lambda-type-vars 1266 #:with (vars …) (remove-ddd #'kw+vars.type-vars) 1267 #:with maybe #'kw+vars) 1268 (pattern (~seq) 1269 #:with (vars …) #'() 1270 #:attr maybe #f)) 1271 1272 (define-splicing-syntax-class new-maybe-type-vars 1273 #:attributes ([vars 1] maybe) 1274 (pattern v:type-variables 1275 #:with (vars …) (remove-ddd #'v) 1276 #:with maybe #'v) 1277 (pattern (~seq) 1278 #:with (vars …) #'() 1279 #:attr maybe #f)) 1280 1281 (define-splicing-syntax-class new-kw-formal 1282 #:attributes ([expanded 1]) 1283 (pattern (~seq kw:keyword id:id) 1284 #:with (expanded ...) #'(kw id)) 1285 (pattern (~seq kw:keyword [id:id 1286 (~optional (~seq :colon type:type-expand!)) 1287 (~optional default:expr)]) 1288 #:with (expanded ...) 1289 (template (kw [id (?@ : type.expanded) 1290 (?? default)])))) 1291 1292 (define-splicing-syntax-class new-mand-formal 1293 #:attributes ([expanded 1]) 1294 (pattern id:id 1295 #:with (expanded ...) #'(id)) 1296 (pattern [id:id :colon type:type-expand!] 1297 #:with (expanded ...) 1298 (template ([id : type.expanded]))) 1299 (pattern kw:new-kw-formal 1300 #:with (expanded ...) #'(kw.expanded ...))) 1301 1302 (define-splicing-syntax-class new-opt-formal 1303 #:attributes ([expanded 1]) 1304 (pattern [id:id 1305 (~optional (~seq :colon type:type-expand!)) 1306 default:expr] 1307 #:with (expanded ...) 1308 (template ([id (?? (?@ : type.expanded)) 1309 default]))) 1310 (pattern kw:new-kw-formal 1311 #:with (expanded ...) #'(kw.expanded ...))) 1312 1313 (define-syntax-class new-rest-arg 1314 #:attributes ([expanded 0]) 1315 (pattern rest:id 1316 #:with expanded #'rest) 1317 (pattern (rest:id 1318 :colon type:type-expand! 1319 (~or (~and x* (~describe "*" (~or (~literal *) 1320 (~literal ...*)))) 1321 (~seq (~literal ...) bound:type-expand!))) 1322 #:with expanded 1323 (template (rest : type.expanded 1324 (?? x* 1325 (?@ (... ...) bound.expanded)))))) 1326 1327 (define-syntax-class new-lambda-formals 1328 (pattern (~or (mand:new-mand-formal ... 1329 opt:new-opt-formal ... 1330 . rest:new-rest-arg) 1331 (mand:new-mand-formal ... 1332 opt:new-opt-formal ...)) 1333 ;; TODO: once template supports ?? in tail position, use it. 1334 #:with expanded #`(mand.expanded ... 1335 ... 1336 opt.expanded ... 1337 ... 1338 . #,(if (attribute rest) 1339 #'rest.expanded 1340 #'())))) 1341 1342 (define-syntax-class (new-curried-formals def-id) 1343 (pattern (f:id . args:new-lambda-formals) 1344 #:with expanded #`(#,def-id . args.expanded)) 1345 (pattern ((~var lhs (new-curried-formals def-id)) 1346 . args:new-lambda-formals) 1347 #:with expanded #'(lhs.expanded . args.expanded))) 1348 1349 (define-syntax-class new-curried-formals-id 1350 (pattern (id:id . _)) 1351 (pattern (lhs:new-curried-formals-id . _) 1352 #:with id #'lhs.id)) 1353 1354 (define-splicing-syntax-class new-optionally-annotated-name 1355 (pattern (~seq name:id (~optional (~seq :colon type:type-expand!))) 1356 #:with expanded 1357 (template (name 1358 (?? (?@ : type.expanded)))))) 1359 1360 (define-syntax-class new-name-or-parenthesised-annotated-name 1361 (pattern name:id 1362 #:with expanded #'name) 1363 (pattern [id:id :colon type:type-expand!] 1364 #:with expanded 1365 (template [id : type.expanded])))] 1366 1367 @subsection{Overview of the overloaded primitives} 1368 1369 The following sections merely define overloads for the 1370 @racketmodname[typed/racket] primitives. The process is 1371 similar each time: a new primitive is defined, e.g. 1372 @tc[new-:] for @|orig::|. The new primitive calls the old one, 1373 after having expanded (using @tc[expand-type]) all parts of 1374 the syntax which contain types. Aside from heavy usage of 1375 @tc[syntax-parse], there is not much to say concerning these 1376 definitions. 1377 1378 @subsection{@racket[:]} 1379 1380 @CHUNK[<:> 1381 (set-:-impl! (syntax-parser 1382 [(_ x:id t:expr) 1383 #`(: x #,(expand-type #'t #f))]))] 1384 1385 @subsection{@racket[define-type]} 1386 1387 @chunk[<define-type> 1388 (define-syntax new-define-type 1389 (syntax-parser 1390 [(_ (~or name:id (name:id maybe-tvar:id …)) . whole-rest) 1391 #:with (tvar …) (if (attribute maybe-tvar) #'(maybe-tvar …) #'()) 1392 #:with (tvar-not-ooo …) (filter (λ (tv) (not (free-identifier=? tv #'(… …)))) 1393 (syntax->list #'(tvar …))) 1394 (start-tl-redirections 1395 (with-bindings [(tvar-not-ooo …) (stx-map <shadowed> 1396 #'(tvar-not-ooo …))] 1397 whole-rest 1398 (syntax-parse #'whole-rest 1399 [(type:type-expand! . rest) 1400 (template 1401 (define-type (?? (name tvar …) name) 1402 type.expanded 1403 . rest))])))]))] 1404 1405 @subsection{@racket[define]} 1406 1407 @chunk[<define> 1408 (define-syntax new-define 1409 (f-start-tl-redirections 1410 (syntax-parser 1411 [(_ {~and (~seq _:new-maybe-kw-type-vars 1412 (~or v:id 1413 formals-id:new-curried-formals-id) 1414 _ …) 1415 (~with-tvars (tvars new-maybe-kw-type-vars) 1416 (~or _:id 1417 (~var formals (new-curried-formals 1418 #'formals-id.id))) 1419 (~optional (~seq :colon type:type-expand!)) 1420 e ...)}) 1421 (template 1422 (define (?? (?@ . tvars.maybe)) (?? v formals.expanded) 1423 (?? (?@ : type.expanded)) 1424 e ...))])))] 1425 1426 @subsection{@racket[lambda]} 1427 1428 @CHUNK[<lambda> 1429 (define-syntax new-lambda 1430 (f-start-tl-redirections 1431 (syntax-parser 1432 [(_ {~with-tvars (tvars new-maybe-kw-type-vars) 1433 args:new-lambda-formals 1434 (~optional (~seq :colon ret-type:type-expand!)) 1435 e …}) 1436 (template (lambda (?? (?@ . tvars.maybe)) args.expanded 1437 (?? (?@ : ret-type.expanded)) 1438 e ...))])))] 1439 1440 @subsection{@racket[case-lambda]} 1441 1442 @CHUNK[<case-lambda> 1443 (define-syntax new-case-lambda 1444 (f-start-tl-redirections 1445 (syntax-parser 1446 [(_ {~with-tvars (tvars new-maybe-kw-type-vars) 1447 [args:new-lambda-formals 1448 (~optional (~seq :colon ret-type:type-expand!)) 1449 e …] 1450 …}) 1451 (template (case-lambda 1452 (?? (?@ #:∀ tvars.maybe)) 1453 [args.expanded 1454 (?? (ann (let () e …) ret-type.expanded) 1455 (?@ e …))] 1456 …))])))] 1457 1458 @subsection{@racket[struct]} 1459 1460 The name must be captured outside of the @racket[~with-tvars], as 1461 @racket[~with-tvars] introduces everything in a new lexical context. 1462 1463 @chunk[<struct> 1464 (define-syntax new-struct 1465 (f-start-tl-redirections 1466 (syntax-parser 1467 [(_ (~and 1468 (~seq _:new-maybe-type-vars 1469 (~and (~seq name+parent …) 1470 (~or (~seq name:id) 1471 (~seq name:id parent:id))) 1472 _ …) 1473 {~with-tvars (tvars new-maybe-type-vars) 1474 (~or (~seq _:id) 1475 (~seq _:id _:id)) 1476 ([field:id :colon type:type-expand!] ...) 1477 rest …})) 1478 (template (struct (?? tvars.maybe) name (?? parent) 1479 ([field : type.expanded] ...) 1480 rest …))])))] 1481 1482 @subsection{@racket[define-struct/exec]} 1483 1484 @chunk[<define-struct/exec> 1485 (define-syntax (new-define-struct/exec stx) 1486 (syntax-parse stx 1487 [(_ (~and name+parent (~or name:id [name:id parent:id])) 1488 ([field:id (~optional (~seq :colon type:type-expand!))] ...) 1489 [proc :colon proc-type:type-expand!]) 1490 (template (define-struct/exec name+parent 1491 ([field (?? (?@ : type.expanded))] ...) 1492 [proc : proc-type.expanded]))]))] 1493 1494 @subsection{@racket[ann]} 1495 1496 @chunk[<ann> 1497 (define-syntax/parse (new-ann value:expr 1498 (~optional :colon) type:type-expand!) 1499 (template (ann value type.expanded)))] 1500 1501 @subsection{@racket[cast]} 1502 1503 @chunk[<cast> 1504 (define-syntax/parse (new-cast value:expr type:type-expand!) 1505 (template (cast value type.expanded)))] 1506 1507 @subsection{@racket[unsafe-cast]} 1508 1509 We additionally define an @racket[unsafe-cast] macro, which Typed/Racket does 1510 not provide yet, but can easily be defined using @racket[unsafe-require/typed] 1511 and a polymorphic function. 1512 1513 @chunk[<unsafe-cast> 1514 (module m-unsafe-cast typed/racket 1515 (provide unsafe-cast-function) 1516 (define (unsafe-cast-function [v : Any]) v)) 1517 1518 (require (only-in typed/racket/unsafe unsafe-require/typed)) 1519 (unsafe-require/typed 'm-unsafe-cast 1520 [unsafe-cast-function (∀ (A) (→ Any A))]) 1521 1522 (define-syntax-rule (unsafe-cast/no-expand v t) 1523 ((inst unsafe-cast-function t) v)) 1524 1525 (define-syntax/parse (unsafe-cast value:expr type:type-expand!) 1526 (template (unsafe-cast/no-expand value type.expanded)))] 1527 1528 @subsection{@racket[inst]} 1529 1530 @chunk[<inst> 1531 (define-syntax new-inst 1532 (syntax-parser 1533 [(_ v (~optional :colon) t:type-expand! ... 1534 last:type-expand! (~literal ...) b:id) 1535 (template (inst v 1536 t.expanded ... 1537 last.expanded (... ...) b))] 1538 [(_ v (~optional :colon) t:type-expand! ...) 1539 (template (inst v t.expanded ...))]))] 1540 1541 @subsection{@racket[row-inst]} 1542 1543 @chunk[<row-inst> 1544 (define-syntax/parse (new-inst e row:type-expand!) 1545 (template (row-inst e row.expanded)))] 1546 1547 @subsection{@racket[let]} 1548 1549 @chunk[<let> 1550 (define-syntax new-let 1551 (f-start-tl-redirections 1552 (syntax-parser 1553 [(_ (~optional (~seq loop:id 1554 (~optional 1555 (~seq :colon return-type:type-expand!)))) 1556 (~with-tvars (tvars new-maybe-kw-type-vars) 1557 ([name:new-optionally-annotated-name e:expr] ...) 1558 rest ...)) 1559 (template 1560 (let (?? (?@ loop (?? (?@ : return-type.expanded)))) 1561 (?@ . tvars) 1562 ([(?@ . name.expanded) e] ...) 1563 rest ...))])))] 1564 1565 @subsection{@racket[let*]} 1566 1567 @chunk[<let*> 1568 (define-syntax/parse 1569 (new-let* 1570 ([name:new-optionally-annotated-name e:expr] ...) 1571 . rest) 1572 (template 1573 (let* ([(?@ . name.expanded) e] ...) . rest)))] 1574 1575 @subsection{@racket[let-values]} 1576 1577 @chunk[<let-values> 1578 (define-syntax/parse 1579 (new-let-values 1580 ([(name:new-name-or-parenthesised-annotated-name ...) e:expr] ...) 1581 . rest) 1582 (template 1583 (let-values ([(name.expanded ...) e] ...) 1584 . rest)))] 1585 1586 @subsection{@racket[make-predicate]} 1587 1588 @chunk[<make-predicate> 1589 (define-simple-macro (new-make-predicate type:type-expand!) 1590 (make-predicate type.expanded))] 1591 1592 @subsection{@racket[:type], @racket[:print-type], @racket[:query-type/args], 1593 @racket[:query-type/result]} 1594 1595 @chunk[<:type> 1596 (define-syntax/parse (new-:type (~optional (~and verbose #:verbose)) 1597 type:type-expand!) 1598 (template (eval #'(#%top-interaction 1599 . (:type (?? verbose) type.expanded)))))] 1600 1601 @chunk[<:print-type> 1602 (define-syntax/parse (new-:print-type e:expr) 1603 #'(:print-type e) 1604 #'(eval #'(#%top-interaction 1605 . (:print-type e))))] 1606 1607 @chunk[<:query-type/args> 1608 (define-syntax/parse (new-:query-type/args f type:type-expand! …) 1609 #'(eval #'(#%top-interaction 1610 . (:query-type/args f type.expanded …))))] 1611 1612 @chunk[<:query-type/result> 1613 (define-syntax/parse (new-:query-type/result f type:type-expand!) 1614 #'(eval #'(#%top-interaction 1615 . (:query-type/result f type.expanded))))] 1616 1617 @subsection{Type expanders for the typed classes} 1618 1619 Not all forms are supported for now. 1620 1621 @chunk[<syntax-classes> 1622 (define-syntax-class field-decl 1623 (pattern id:id #:with expanded #'(field id)) 1624 (pattern (maybe-renamed {~optional {~seq :colon type:type-expand!}} 1625 {~optional default-value-expr}) 1626 #:with expanded 1627 (template (maybe-renamed (?? (?@ : type.expanded)) 1628 (?? default-value-expr)))))] 1629 1630 @chunk[<syntax-classes> 1631 (define-syntax-class field-clause 1632 #:literals (field) 1633 (pattern (field field-decl:field-decl …) 1634 #:with expanded (template (field field-decl.expanded …))))] 1635 1636 @chunk[<syntax-classes> 1637 (define-syntax-class super-new-clause 1638 #:literals (super-new) 1639 (pattern (super-new . rest) 1640 #:with expanded (template (super-new . rest))))] 1641 1642 @;{ 1643 @chunk[<field> 1644 (set-field-impl! 1645 (syntax-parser [clause:field-clause #'clause.expanded]))] 1646 1647 @chunk[<super-new> 1648 (set-super-new-impl! 1649 (syntax-parser [clause:super-new-clause #'clause.expanded]))]} 1650 1651 1652 @chunk[<syntax-classes> 1653 (define-syntax-class class-clause 1654 #:attributes (expanded) 1655 (pattern :field-clause) 1656 (pattern :super-new-clause))] 1657 1658 @chunk[<class> 1659 (define-syntax new-class 1660 (f-start-tl-redirections 1661 (syntax-parser 1662 [(_ superclass-expr 1663 {~with-tvars (tvars new-maybe-kw-type-vars) 1664 clause:class-clause ...}) 1665 (template (class superclass-expr 1666 (?? (?@ . tvars.maybe)) 1667 clause.expanded ...))])))] 1668 1669 @subsection[#:tag "type-expander|other-forms"]{Other @racket[typed/racket] 1670 forms} 1671 1672 The other @tc[typed/racket] forms below do not have an alternative definition 1673 yet. 1674 1675 @chunk[<other-forms> 1676 (define-syntax (missing-forms stx) 1677 (syntax-parse stx 1678 [(_ name ...) 1679 (define/with-syntax (tmp ...) (generate-temporaries #'(name ...))) 1680 #'(begin 1681 (begin 1682 (define-syntax (tmp stx) 1683 (raise-syntax-error 1684 'name 1685 (format "~a not implemented yet for type-expander" 'name) 1686 stx)) 1687 (provide (rename-out [tmp name]))) 1688 ...)])) 1689 1690 (missing-forms 1691 (code:comment ";TODO: add all-defined-out in prims.rkt") 1692 (code:comment "; top-interaction.rkt") 1693 (code:comment ":type") 1694 (code:comment ":print-type") 1695 (code:comment ":query-type/args") 1696 (code:comment ":query-type/result") 1697 (code:comment "; case-lambda.rkt") 1698 (code:comment "case-lambda") 1699 (code:comment "case-lambda:") 1700 pcase-lambda: 1701 (code:comment "; (submod \"prims-contract.rkt\" forms)") 1702 require/opaque-type 1703 (code:comment "require-typed-struct-legacy") 1704 require-typed-struct 1705 (code:comment "require/typed-legacy") 1706 require/typed 1707 require/typed/provide 1708 require-typed-struct/provide 1709 (code:comment "cast") 1710 (code:comment "make-predicate") 1711 define-predicate 1712 (code:comment "; prims.rkt") 1713 define-type-alias 1714 define-new-subtype 1715 define-typed-struct 1716 define-typed-struct/exec 1717 (code:comment "ann") 1718 (code:comment "inst") 1719 (code:comment ":") 1720 define-struct: 1721 define-struct 1722 (code:comment "struct") 1723 struct: 1724 λ: 1725 lambda: 1726 (code:comment "lambda") 1727 (code:comment "λ") 1728 (code:comment "define") 1729 (code:comment "let") 1730 (code:comment "let*") 1731 letrec 1732 (code:comment "let-values") 1733 letrec-values 1734 let/cc 1735 let/ec 1736 let: 1737 let*: 1738 letrec: 1739 let-values: 1740 letrec-values: 1741 let/cc: 1742 let/ec: 1743 for 1744 for/list 1745 for/vector 1746 for/hash 1747 for/hasheq 1748 for/hasheqv 1749 for/and 1750 for/or 1751 for/sum 1752 for/product 1753 for/lists 1754 for/first 1755 for/last 1756 for/fold 1757 for* 1758 for*/list 1759 for*/lists 1760 for*/vector 1761 for*/hash 1762 for*/hasheq 1763 for*/hasheqv 1764 for*/and 1765 for*/or 1766 for*/sum 1767 for*/product 1768 for*/first 1769 for*/last 1770 for*/fold 1771 for/set 1772 for*/set 1773 do 1774 do: 1775 with-handlers 1776 define-struct/exec: 1777 (code:comment "define-struct/exec"))] 1778 1779 @section{Future work} 1780 1781 We have not implemented alternative type-expanding definitions for all the 1782 @tc[typed/racket] forms, as noted in @secref{type-expander|other-forms}. 1783 1784 Integrating the type expander directly into typed/racket 1785 would avoid the need to provide such definitions, and allow 1786 using type expanders in vanilla @tc[typed/racket], instead 1787 of having to @racket[require] this library. However, the 1788 code wrapping the @tc[typed/racket] forms could be re-used 1789 by other libraries that alter the way @tc[typed/racket] 1790 works, so implementing the remaining forms could still be 1791 useful. 1792 1793 Also, we would need to provide a @tc[syntax-local-type-introduce] function, 1794 similar to the @tc[syntax-local-match-introduce] function provided by @tc[match] 1795 for example. 1796 1797 @section{Conclusion} 1798 1799 When an identifier is @racket[require]d from another module, 1800 it is not the same as the one visible within the defining 1801 module. This is a problem for @tc[:], because we match 1802 against it in our syntax classes, using @tc[(~literal :)], 1803 but when it is written in another module, for example 1804 @tc[(define foo : Number 42)], it is not the same identifier 1805 as the one used by original definition of @tc[:], and 1806 therefore the @tc[(~literal :)] won't match. I suspect that 1807 issue to be due to contract wrappers added by 1808 @tc[typed/racket]. 1809 1810 To get around that problem, we define @tc[:] in a separate module, and 1811 @racket[require] it in the module containing the syntax classes: 1812 1813 Since our @tc[new-:] macro needs to call the 1814 @tc[type-expander], and the other forms too, we cannot 1815 define @tc[type-expander] in the same module as these forms, 1816 it needs to be either in the same module as @tc[new-:], or 1817 in a separate module. Additionally, @tc[expand-type] needs 1818 to be required @tc[for-syntax] by the forms, but needs to be 1819 @tc[provide]d too, so it is much easier if it is defined in 1820 a separate module (that will be used only by macros, so it 1821 will be written in @tc[racket], not @tc[typed/racket]). 1822 1823 @chunk[<module-expander> 1824 (module expander racket 1825 (require (for-template typed/racket 1826 "identifiers.rkt") 1827 racket 1828 (only-in racket/base [... …]) 1829 syntax/parse 1830 racket/format 1831 racket/syntax 1832 syntax/id-table 1833 syntax/stx 1834 auto-syntax-e 1835 "parameterize-lexical-context.rkt" 1836 debug-scopes 1837 racket/contract/base) 1838 ;; TODO: move this in a separate chunk and explain it 1839 1840 (provide prop:type-expander 1841 (contract-out 1842 (rename has-prop:type-expander? 1843 prop:type-expander? 1844 (-> any/c boolean?)) 1845 (rename get-prop:type-expander-value 1846 prop:type-expander-ref 1847 (-> has-prop:type-expander? 1848 any/c))) 1849 type-expander 1850 apply-type-expander 1851 ;bind-type-vars 1852 expand-type 1853 type 1854 stx-type/c 1855 type-expand! 1856 debug-type-expander? 1857 patched 1858 make-type-expander) 1859 1860 <remove-ddd> 1861 1862 <prop-guard> 1863 <prop:type-expander> 1864 <type-expander-struct> 1865 1866 <patched> 1867 1868 <apply-type-expander> 1869 ;<expand-quasiquote> 1870 <type-syntax-class> 1871 <type-contract> 1872 <expand-type-debug-outer> 1873 <expand-type> 1874 <type-expand-syntax-class>)] 1875 1876 We can finally define the overloaded forms, as well as the 1877 @tc[<define-type-expander>] form. 1878 1879 @chunk[<module-main> 1880 (module main typed/racket 1881 (require (only-in typed/racket/base [... …]) 1882 typed/racket/class 1883 (for-syntax racket 1884 (only-in racket/base [... …]) 1885 racket/syntax 1886 syntax/parse 1887 syntax/parse/experimental/template 1888 syntax/id-table 1889 "parameterize-lexical-context.rkt" 1890 syntax/stx) 1891 (for-meta 2 racket/base syntax/parse) 1892 "utils.rkt" 1893 syntax/parse/define 1894 "identifiers.rkt") 1895 1896 (require (submod ".." expander)) 1897 (require (for-syntax (submod ".." expander))) 1898 (require (for-syntax typed-racket/base-env/annotate-classes)) 1899 1900 (provide prop:type-expander 1901 prop:type-expander? 1902 prop:type-expander-ref 1903 expand-type 1904 define-type-expander 1905 patch-type-expander 1906 Let 1907 Letrec 1908 Λ 1909 ...* 1910 No-Expand 1911 unsafe-cast/no-expand 1912 unsafe-cast 1913 debug-type-expander 1914 (rename-out [new-: :] 1915 [new-define-type define-type] 1916 [new-define define] 1917 [new-lambda lambda] 1918 [new-lambda λ] 1919 [new-case-lambda case-lambda] 1920 [new-case-lambda case-lambda:] 1921 [new-struct struct] 1922 [new-define-struct/exec define-struct/exec] 1923 [new-ann ann] 1924 [new-cast cast] 1925 [new-inst inst] 1926 [new-let let] 1927 [new-let* let*] 1928 [new-let-values let-values] 1929 [new-make-predicate make-predicate] 1930 [new-:type :type] 1931 [new-:print-type :print-type] 1932 [new-:query-type/args :query-type/args] 1933 [new-:query-type/result :query-type/result] 1934 ;[new-field field] 1935 ;[new-super-new super-new] 1936 [new-class class])) 1937 1938 (begin-for-syntax 1939 (define-syntax ~with-tvars 1940 (pattern-expander 1941 (syntax-parser 1942 [(_ (tv tv-stxclass) pat ...) 1943 #'{~seq {~var tmp-tv tv-stxclass} 1944 {~seq whole-rest (... ...)} 1945 {~parse (({~var tv tv-stxclass}) pat ...) 1946 ;; rebind tvars: 1947 (with-bindings [(tmp-tv.vars (... ...)) 1948 (stx-map <shadowed> 1949 #'(tmp-tv.vars (... ...)))] 1950 ;; rebind occurrences of the tvars within: 1951 (tmp-tv whole-rest (... ...)) 1952 ;; to (re-)parse: 1953 #'(tmp-tv whole-rest (... ...)))}}])))) 1954 1955 <debug-type-expander> 1956 1957 <:> 1958 1959 <define-type-expander> 1960 <patch> 1961 1962 (begin-for-syntax 1963 <remove-ddd> 1964 <syntax-classes> 1965 1966 (provide colon)) 1967 1968 <define-type> 1969 <define> 1970 <lambda> 1971 <case-lambda> 1972 <struct> 1973 <define-struct/exec> 1974 <ann> 1975 <cast> 1976 <unsafe-cast> 1977 <inst> 1978 <let> 1979 <let*> 1980 <let-values> 1981 <make-predicate> 1982 <:type> 1983 <:print-type> 1984 <:query-type/args> 1985 <:query-type/result> 1986 ;<field> 1987 <class> 1988 ;<super-new> 1989 <other-forms>)] 1990 1991 We can now assemble the modules in this order: 1992 1993 @chunk[<*> 1994 <module-expander> 1995 <module-main> 1996 1997 (require 'main) 1998 (provide (except-out (all-from-out 'main) (for-syntax colon)))]