|
6 | 6 | syntax/parse/experimental/template |
7 | 7 | syntax/intdef |
8 | 8 | syntax/srcloc |
9 | | - threading) |
| 9 | + syntax/parse/class/local-value |
| 10 | + threading |
| 11 | + serialize-syntax-introducer) |
10 | 12 | (postfix-in - (combine-in racket/base |
11 | 13 | racket/promise)) |
12 | 14 | racket/stxparam |
|
26 | 28 | @%superclasses-key @%dictionary-placeholder @%with-dictionary #%defer-expansion |
27 | 29 | define-primop define-base-type |
28 | 30 | -> Integer Double String |
29 | | - : λ1 def let letrec todo!) |
| 31 | + : ⋮ λ1 def let letrec todo!) |
30 | 32 |
|
31 | 33 | (define-base-type Integer) |
32 | 34 | (define-base-type Double) |
|
324 | 326 |
|
325 | 327 | ;; --------------------------------------------------------------------------------------------------- |
326 | 328 |
|
| 329 | +(begin-for-syntax |
| 330 | + ; Instances of this struct are created by `⋮` when declaring the types of bindings |
| 331 | + ; seperately from their definitions. When a binding is defined (with `def` or related |
| 332 | + ; forms), it searches for a `binding-declaration` and fills in `internal-id` with the |
| 333 | + ; actual definition. The `type` field is used as the expected type of the definition. |
| 334 | + ; fixity : [Maybe Fixity] |
| 335 | + (struct binding-declaration [internal-id type scoped-binding-introducer fixity] |
| 336 | + #:property prop:procedure |
| 337 | + (λ (this stx) |
| 338 | + (match-define (binding-declaration x- type _ _) this) |
| 339 | + ((make-typed-var-transformer x- type) stx)) |
| 340 | + #:property prop:infix-operator |
| 341 | + (λ (this) (binding-declaration-fixity this))) |
| 342 | + |
| 343 | + (define-syntax-class id/binding-declaration |
| 344 | + #:attributes [internal-id type scoped-binding-introducer fixity] |
| 345 | + [pattern (~var x (local-value binding-declaration?)) |
| 346 | + #:do [(match-define (binding-declaration x-* type* sbi* fixity*) |
| 347 | + (attribute x.local-value))] |
| 348 | + #:attr internal-id (syntax-local-introduce x-*) |
| 349 | + #:with type (syntax-local-introduce type*) |
| 350 | + #:attr scoped-binding-introducer (deserialize-syntax-introducer sbi*) |
| 351 | + #:attr fixity fixity*])) |
| 352 | + |
| 353 | +(define-syntax-parser define/binding-declaration |
| 354 | + [(_ x:id/binding-declaration rhs) |
| 355 | + #:with x- #'x.internal-id |
| 356 | + #'(define- x- rhs)]) |
| 357 | + |
| 358 | +;; --------------------------------------------------------------------------------------------------- |
| 359 | + |
327 | 360 | (define-syntax-parser @%module-begin |
328 | 361 | [(_ form ...) |
329 | 362 | (~> (local-expand (value-namespace-introduce |
|
343 | 376 | [(_ . x) |
344 | 377 | (raise-syntax-error #f "literal not supported" #'x)]) |
345 | 378 |
|
346 | | -(define-syntax-parser : |
347 | | - ; The #:exact option prevents : from performing context reduction. This is not normally important, |
348 | | - ; but it is required for forms that use : to ensure an expression has a particular shape in order to |
349 | | - ; interface with untyped (i.e. Racket) code, and therefore the resulting type is ignored. For |
350 | | - ; example, the def form wraps an expression in its expansion with :, but it binds the actual |
351 | | - ; identifier to a syntax transformer that attaches the type directly. Therefore, it needs to perform |
352 | | - ; context reduction itself prior to expanding to :, and it must use #:exact. |
353 | | - [(_ e {~type t:type} {~optional {~and #:exact exact?}}) |
354 | | - #:with t_reduced (if (attribute exact?) |
355 | | - #'t.expansion |
356 | | - (type-reduce-context #'t.expansion)) |
357 | | - (attach-type #`(let-values- ([() t.residual]) |
358 | | - #,(τ⇐! ((attribute t.scoped-binding-introducer) #'e) #'t_reduced)) |
359 | | - #'t_reduced)]) |
| 379 | +;; The `:` form annotates an expression with an expected type. |
| 380 | +(define-syntax : |
| 381 | + (λ (stx) |
| 382 | + (syntax-parse stx |
| 383 | + ; The #:exact option prevents : from performing context reduction. This is not normally important, |
| 384 | + ; but it is required for forms that use : to ensure an expression has a particular shape in order to |
| 385 | + ; interface with untyped (i.e. Racket) code, and therefore the resulting type is ignored. For |
| 386 | + ; example, the def form wraps an expression in its expansion with :, but it binds the actual |
| 387 | + ; identifier to a syntax transformer that attaches the type directly. Therefore, it needs to perform |
| 388 | + ; context reduction itself prior to expanding to :, and it must use #:exact. |
| 389 | + [(_ e {~type t:type} {~optional {~and #:exact exact?}}) |
| 390 | + #:with t_reduced (if (attribute exact?) |
| 391 | + #'t.expansion |
| 392 | + (type-reduce-context #'t.expansion)) |
| 393 | + (attach-type #`(let-values- ([() t.residual]) |
| 394 | + #,(τ⇐! ((attribute t.scoped-binding-introducer) #'e) #'t_reduced)) |
| 395 | + #'t_reduced)]))) |
| 396 | + |
| 397 | +;; The `⋮` form declares that an id will be defined with an expected type. |
| 398 | +;; For example: |
| 399 | +;; (⋮ x τ) |
| 400 | +;; (def x e) |
| 401 | +;; Defines `x` with type `τ` to be equal to the value produced by `e`, |
| 402 | +;; which must produce |
| 403 | +(define-syntax ⋮ |
| 404 | + (λ (stx) |
| 405 | + (syntax-parse stx |
| 406 | + [(_ x:id {~type t:type} |
| 407 | + {~alt {~optional {~and #:exact exact?}} |
| 408 | + {~optional f:fixity-annotation}} |
| 409 | + ...) |
| 410 | + #:with x- (generate-temporary #'x) |
| 411 | + #:with exct? (and (attribute exact?) #true) |
| 412 | + #:with fixity (attribute f.fixity) |
| 413 | + #:with t_reduced (if (attribute exact?) |
| 414 | + #'t.expansion |
| 415 | + (type-reduce-context #'t.expansion)) |
| 416 | + #:with sbi (serialize-syntax-introducer |
| 417 | + (attribute t.scoped-binding-introducer)) |
| 418 | + #`(begin- |
| 419 | + (define-values- [] t.residual) |
| 420 | + (define-syntax- x |
| 421 | + (binding-declaration |
| 422 | + (quote-syntax x-) |
| 423 | + (quote-syntax t_reduced) |
| 424 | + (quote-syntax sbi) |
| 425 | + 'fixity)))]))) |
360 | 426 |
|
361 | 427 | (define-syntax-parser λ1 |
362 | 428 | [(_ x:id e:expr) |
|
383 | 449 |
|
384 | 450 | (define-syntax-parser def |
385 | 451 | #:literals [:] |
386 | | - [(_ id:id |
387 | | - {~or {~once {~seq {~and : {~var :/use}} {~type t:type} |
388 | | - {~optional {~and #:exact exact?}}}} |
389 | | - {~optional fixity:fixity-annotation}} |
390 | | - ... |
| 452 | + [(_ x:id/binding-declaration e:expr) |
| 453 | + #:with x- #'x.internal-id |
| 454 | + (syntax-property |
| 455 | + #`(define- x- |
| 456 | + (: #,((attribute x.scoped-binding-introducer) #'e) |
| 457 | + x.type |
| 458 | + #:exact)) |
| 459 | + 'disappeared-use |
| 460 | + (syntax-local-introduce #'x))] |
| 461 | + |
| 462 | + [(_ x:id : type:expr |
| 463 | + {~and {~seq stuff ...} |
| 464 | + {~seq {~alt {~optional {~and #:exact exact?}} |
| 465 | + {~optional f:fixity-annotation}} |
| 466 | + ...}} |
391 | 467 | e:expr) |
392 | | - #:with id- (generate-temporary #'id) |
393 | | - #:with t_reduced (if (attribute exact?) #'t.expansion (type-reduce-context #'t.expansion)) |
394 | | - #`(begin- |
395 | | - #,(indirect-infix-definition |
396 | | - #'(define-syntax- id (make-typed-var-transformer #'id- (quote-syntax t_reduced))) |
397 | | - (attribute fixity.fixity)) |
398 | | - (define- id- (:/use #,((attribute t.scoped-binding-introducer) #'e) t_reduced #:exact)))] |
| 468 | + #'(begin- |
| 469 | + (⋮ x type stuff ...) |
| 470 | + (def x e))] |
| 471 | + |
399 | 472 | [(_ id:id |
400 | | - {~optional fixity:fixity-annotation} |
| 473 | + {~and {~seq fixity-stuff ...} |
| 474 | + {~optional fixity:fixity-annotation}} |
401 | 475 | e:expr) |
402 | | - #:with x^ (generate-temporary) |
| 476 | + #:with x^ (generate-temporary #'z) |
403 | 477 | #:with t_e #'(#%type:wobbly-var x^) |
404 | 478 | #:do [(match-define-values [(list id-) e-] (τ⇐/λ! #'e #'t_e (list (cons #'id #'t_e))))] |
405 | 479 | #:with t_gen (type-reduce-context (generalize (apply-current-subst #'t_e))) |
| 480 | + #:with id-/gen (attach-type id- #'t_gen) |
406 | 481 | #`(begin- |
407 | | - #,(indirect-infix-definition |
408 | | - #`(define-syntax- id (make-typed-var-transformer (quote-syntax #,id-) (quote-syntax t_gen))) |
409 | | - (attribute fixity.fixity)) |
410 | | - (define- #,id- #,e-))]) |
| 482 | + (⋮ id t_gen fixity-stuff ... #:exact) |
| 483 | + (define/binding-declaration id |
| 484 | + (let-syntax ([id-/gen |
| 485 | + (make-rename-transformer (quote-syntax id))]) |
| 486 | + #,e-)))]) |
| 487 | + |
411 | 488 |
|
412 | 489 | (begin-for-syntax |
413 | 490 | (struct todo-item (full summary) #:prefab)) |
|
0 commit comments