More literate explanations
This commit is contained in:
parent
cae1d4d430
commit
fe3eec2b44
|
@ -304,7 +304,6 @@ fields.
|
||||||
#:node-wrapper λl.r.(list #'cons l r)
|
#:node-wrapper λl.r.(list #'cons l r)
|
||||||
#:vec vec)]
|
#:vec vec)]
|
||||||
|
|
||||||
꩜section{Type of a record, with a multiple holes}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -349,10 +348,11 @@ fields.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
꩜section{Row typing}
|
||||||
|
|
||||||
Identifiers which are bound as row type variables are bound as transformers to
|
Row type variable identifiers are bound as transformers to instances of the
|
||||||
instances of the ꩜racket[ρ-wrapper] struct, so that they are easily
|
꩜racket[ρ-wrapper] struct, so that they are easily recognisable by special
|
||||||
recognizable by special forms such as ꩜racket[record].
|
forms such as ꩜racket[record].
|
||||||
|
|
||||||
꩜spler[<ρ-wrapper>
|
꩜spler[<ρ-wrapper>
|
||||||
(begin-for-syntax
|
(begin-for-syntax
|
||||||
|
@ -367,9 +367,10 @@ recognizable by special forms such as ꩜racket[record].
|
||||||
stx))))]
|
stx))))]
|
||||||
|
|
||||||
The row type variable actually expands to several polymorphic type variables.
|
The row type variable actually expands to several polymorphic type variables.
|
||||||
In order to know which, we remember which fields are used along a given row
|
In order to know which fields are relevant, we remember which fields are used
|
||||||
type variable, while compiling the current file. The set of field names used
|
along a given row type variable, while compiling the current file. The set of
|
||||||
with a given row types variable is stored as an entry of the ꩜racket[ρ-table].
|
field names used with a given row types variable is stored as an entry of the
|
||||||
|
꩜racket[ρ-table].
|
||||||
|
|
||||||
꩜chunk[<ρ-table>
|
꩜chunk[<ρ-table>
|
||||||
(define-for-syntax ρ-table (make-free-id-table))]
|
(define-for-syntax ρ-table (make-free-id-table))]
|
||||||
|
@ -410,10 +411,11 @@ dimmed below.
|
||||||
(define sidekicks '())
|
(define sidekicks '())
|
||||||
#`(∀ (arg … #,@sidekicks) tree)]))]
|
#`(∀ (arg … #,@sidekicks) tree)]))]
|
||||||
|
|
||||||
Aside from the kind of result (which is a polymorphic type, not a function),
|
The results of ꩜racket[record-type] and ꩜racket[record-builder] differ in two
|
||||||
the main difference with ꩜racket[idx→tree] is how the empty branches are
|
aspects: the result of ꩜racket[record-type] is a polymorphic type, not a
|
||||||
handled. When a branch only containing ꩜racket[none] elements is encountered,
|
function, and the empty branches are handled differently. When a branch only
|
||||||
it is replaced with a single polymorphic type.
|
containing ꩜racket[none] elements is encountered, it is replaced with a single
|
||||||
|
polymorphic type.
|
||||||
|
|
||||||
꩜hlite[<record-type/wrappers> {-/ (_ = _ _ _ _ _ _ _ _ _ -/ _ vec)}
|
꩜hlite[<record-type/wrappers> {-/ (_ = _ _ _ _ _ _ _ _ _ -/ _ vec)}
|
||||||
(idx→tree
|
(idx→tree
|
||||||
|
@ -436,39 +438,65 @@ which will produce the syntax for the desired type when called.
|
||||||
꩜chunk[<current-patch-table>
|
꩜chunk[<current-patch-table>
|
||||||
(define-for-syntax current-patch-table (make-parameter #f))]
|
(define-for-syntax current-patch-table (make-parameter #f))]
|
||||||
|
|
||||||
꩜chunk[<record-type>
|
Type-level forms like ꩜racket[∀ρ], ꩜racket[ρ-inst] and ꩜racket[record] add
|
||||||
<ρ-wrapper>
|
placeholders to ꩜racket[current-patch-table].
|
||||||
<current-patch-table>
|
|
||||||
|
The form ꩜racket[with-ρ] is used to declare row type variables and collect
|
||||||
|
patches in ꩜racket[current-patch-table]. The explicit declaration of row type
|
||||||
|
variables is necessary because type variables which are logically ``bound''
|
||||||
|
with ꩜racket[∀] are not actually bound as identifiers during macro expansion
|
||||||
|
(instead, Typed Racket performs its own resolution while typechecking, i.e.
|
||||||
|
after the program is expanded). If a row type variable is introduced in the
|
||||||
|
type declaration for a function, we need to be able to detect the binding when
|
||||||
|
processing type-level forms within the body of the function.
|
||||||
|
|
||||||
|
꩜chunk[<with-ρ>
|
||||||
|
(define-syntax with-ρ
|
||||||
|
(syntax-parser
|
||||||
|
[(_ (ρ …) . body)
|
||||||
|
#'(splicing-letrec-syntax ([ρ (ρ-wrapper #'ρ)] …)
|
||||||
|
(with-ρ-chain (ρ …) . body))]))]
|
||||||
|
|
||||||
|
Once the bindings have been introduced via ꩜racket[splicing-letrec-syntax],
|
||||||
|
the expansion continues within the context of these identifiers, via the
|
||||||
|
꩜racket[with-ρ-chain] macro.
|
||||||
|
|
||||||
|
꩜chunk[<with-ρ-chain>
|
||||||
(define-syntax with-ρ-chain
|
(define-syntax with-ρ-chain
|
||||||
(syntax-parser
|
(syntax-parser
|
||||||
[(_ (ρ …) . body)
|
[(_ (ρ …) . body)
|
||||||
(parameterize ([current-patch-table (make-free-id-table)])
|
(parameterize ([current-patch-table (make-free-id-table)])
|
||||||
(define expanded-form
|
(define expanded-form
|
||||||
(local-expand #'(begin . body) 'top-level '()))
|
(local-expand #'(begin . body) 'top-level '()))
|
||||||
(patch expanded-form (current-patch-table)))]))
|
(patch expanded-form (current-patch-table)))]))]
|
||||||
(define-syntax with-ρ
|
|
||||||
(syntax-parser
|
|
||||||
[(_ (ρ …) . body)
|
|
||||||
#'(splicing-letrec-syntax ([ρ (ρ-wrapper #'ρ)] …)
|
|
||||||
(with-ρ-chain (ρ …) . body))]))
|
|
||||||
|
|
||||||
<ρ-table>
|
꩜subsection{Type of a record, with a multiple fields}
|
||||||
|
|
||||||
|
The ꩜racket[∀ρ] type-level form translates to a ꩜racket[∀] form. The
|
||||||
|
꩜racket[∀] form is expanded, so that uses of the row type variables within can
|
||||||
|
be detected. The ꩜racket[∀ρ] then expands to a placeholder
|
||||||
|
꩜racket[delayed-type], which will be patched by the surrounding
|
||||||
|
꩜racket[with-ρ].
|
||||||
|
|
||||||
|
꩜;TODO: use a table to track the pre-declared collapsed-branch types?
|
||||||
|
꩜chunk[<∀ρ>
|
||||||
(define-type-expander ∀ρ
|
(define-type-expander ∀ρ
|
||||||
(syntax-parser
|
(syntax-parser
|
||||||
[(_ (A:id … #:ρ ρ:id …) τ)
|
[(_ (A:id … #:ρ ρ:id …) τ)
|
||||||
(for ([ρ (in-syntax #'(ρ …))])
|
(for ([ρ (in-syntax #'(ρ …))])
|
||||||
(free-id-table-set! ρ-table ρ <make-lifo-set>))
|
(free-id-table-set! ρ-table ρ <make-lifo-set>))
|
||||||
(define expanded (expand-type #'(∀ (A …)
|
(define expanded (expand-type #'(∀ (A …) (Let ([ρ 'NOT-IMPL-YET] …) τ))))
|
||||||
(Let ([ρ (Pairof 'Hello 'ρ)]
|
|
||||||
…)
|
|
||||||
τ))))
|
|
||||||
(define/syntax-parse ({~literal tr:∀} (A′ …) . τ′) expanded)
|
(define/syntax-parse ({~literal tr:∀} (A′ …) . τ′) expanded)
|
||||||
(free-id-table-set! (current-patch-table)
|
(free-id-table-set! (current-patch-table)
|
||||||
#'delayed-type
|
#'delayed-type
|
||||||
(λ (self)
|
(λ (self) (delayed-∀ρ #'{(A′ …) (ρ …) τ′})))
|
||||||
(delayed-∀ρ #'{(A′ …) (ρ …) τ′})))
|
#'delayed-type]))]
|
||||||
#'delayed-type]))
|
|
||||||
|
|
||||||
|
When the ꩜racket[delayed-type] is replaced, the type variables associated with
|
||||||
|
each row type variable are injected as extra arguments to the
|
||||||
|
previously-expanded polymorphic type.
|
||||||
|
|
||||||
|
꩜chunk[<delayed-∀ρ>
|
||||||
(define-for-syntax/case-args (delayed-∀ρ {(A′ …) (ρ …) τ′})
|
(define-for-syntax/case-args (delayed-∀ρ {(A′ …) (ρ …) τ′})
|
||||||
(define/syntax-parse ((ρ′ …) …)
|
(define/syntax-parse ((ρ′ …) …)
|
||||||
(for/list ([ρ (in-syntax #'(ρ …))])
|
(for/list ([ρ (in-syntax #'(ρ …))])
|
||||||
|
@ -479,7 +507,21 @@ which will produce the syntax for the desired type when called.
|
||||||
;; the id is added to the list. Also #'here is probably the
|
;; the id is added to the list. Also #'here is probably the
|
||||||
;; wrong srcloc
|
;; wrong srcloc
|
||||||
(format-id #'here "~a.~a" ρ ρ′))))
|
(format-id #'here "~a.~a" ρ ρ′))))
|
||||||
#'(∀ (A′ … ρ′ … …) . τ′))
|
#'(∀ (A′ … ρ′ … …) . τ′))]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
꩜chunk[<record-type>
|
||||||
|
<ρ-wrapper>
|
||||||
|
<current-patch-table>
|
||||||
|
|
||||||
|
<with-ρ-chain>
|
||||||
|
<with-ρ>
|
||||||
|
|
||||||
|
<ρ-table>
|
||||||
|
<∀ρ>
|
||||||
|
|
||||||
|
<delayed-∀ρ>
|
||||||
|
|
||||||
(define-type-expander record
|
(define-type-expander record
|
||||||
(syntax-parser
|
(syntax-parser
|
||||||
|
|
Loading…
Reference in New Issue
Block a user