Make initial version of structural type recursion, and use it.
This commit is contained in:
parent
cadc2dcb8f
commit
9efa4af051
|
@ -2,7 +2,7 @@
|
|||
|
||||
(require "../utils/utils.rkt"
|
||||
(rep type-rep rep-utils)
|
||||
(types abbrev union utils)
|
||||
(types abbrev union utils structural)
|
||||
racket/list racket/match)
|
||||
|
||||
(provide/cond-contract
|
||||
|
@ -24,21 +24,21 @@
|
|||
(define-values (var-promote var-demote)
|
||||
(let ()
|
||||
(define (var-change V T change)
|
||||
(define (co t) (var-change V t change))
|
||||
(define (contra t) (var-change V t (not change)))
|
||||
(define (inv t)
|
||||
(define (structural-recur t sym)
|
||||
(case sym
|
||||
[(co) (var-change V t change)]
|
||||
[(contra) (var-change V t (not change))]
|
||||
[(inv)
|
||||
(if (V-in? V t)
|
||||
(if change Univ -Bottom)
|
||||
t))
|
||||
(type-case (#:Type co #:Filter (sub-f co)) T
|
||||
[#:F name (if (memq name V) (if change Univ -Bottom) T)]
|
||||
[#:Vector t (make-Vector (inv t))]
|
||||
[#:Box t (make-Box (inv t))]
|
||||
[#:Channel t (make-Channel (inv t))]
|
||||
[#:ThreadCell t (make-ThreadCell (inv t))]
|
||||
[#:Hashtable k v (make-Hashtable (inv k) (inv v))]
|
||||
[#:Param in out (make-Param (contra in) (co out))]
|
||||
[#:arr dom rng rest drest kws
|
||||
t)]))
|
||||
(define (co t) (structural-recur t 'co))
|
||||
(define (contra t) (structural-recur t 'contra))
|
||||
|
||||
(match T
|
||||
[(? structural?) (structural-map T structural-recur)]
|
||||
[(F: name) (if (memq name V) (if change Univ -Bottom) T)]
|
||||
[(arr: dom rng rest drest kws)
|
||||
(cond
|
||||
[(apply V-in? V (get-filters rng))
|
||||
(make-top-arr)]
|
||||
|
@ -53,7 +53,11 @@
|
|||
(co rng)
|
||||
(and rest (contra rest))
|
||||
(and drest (cons (contra (car drest)) (cdr drest)))
|
||||
(map contra kws))])]))
|
||||
(map contra kws))])]
|
||||
[(? Filter?) ((sub-f co) T)]
|
||||
[(? Object?) ((sub-o co) T)]
|
||||
[(? Type?) ((sub-t co) T)]))
|
||||
|
||||
(values
|
||||
(lambda (T V) (var-change V T #t))
|
||||
(lambda (T V) (var-change V T #f)))))
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
free-vars*
|
||||
type-compare type<?
|
||||
remove-dups
|
||||
sub-f sub-o sub-pe
|
||||
sub-t sub-f sub-o sub-pe
|
||||
(rename-out [Class:* Class:]
|
||||
[Class* make-Class]
|
||||
[Row* make-Row]
|
||||
|
@ -618,6 +618,12 @@
|
|||
#:PathElem (sub-pe st))
|
||||
e))
|
||||
|
||||
(define ((sub-t st) e)
|
||||
(type-case (#:Type st
|
||||
#:Filter (sub-f st))
|
||||
e))
|
||||
|
||||
|
||||
;; abstract-many : Names Type -> Scope^n
|
||||
;; where n is the length of names
|
||||
(define (abstract-many names ty)
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
#lang racket/base
|
||||
|
||||
;; Module for providing recursive operations over types when the operation doesn't care about the
|
||||
;; type constructor.
|
||||
|
||||
;; This file is meant to implement more general versions of type-case.
|
||||
;; Currently supported
|
||||
;; * Trivial type constructors (only have Rep? or (listof Rep?) fields)
|
||||
;; * A variance aware traversal of a Rep? with the return value having the same type constructor as
|
||||
;; the input.
|
||||
;; To be added
|
||||
;; * Support for type constructors with non Rep? fields
|
||||
;; * Support for objects and filters
|
||||
;; * Support for smart constructors for the return value
|
||||
;; * Support for return values that are not Rep?
|
||||
;; * Parallel traversal of two types
|
||||
|
||||
(require
|
||||
"../utils/utils.rkt"
|
||||
racket/match
|
||||
(rep type-rep)
|
||||
(for-syntax
|
||||
racket/base
|
||||
syntax/parse
|
||||
racket/syntax
|
||||
unstable/sequence))
|
||||
(provide
|
||||
structural?
|
||||
structural-map)
|
||||
|
||||
|
||||
(define-for-syntax structural-reps
|
||||
#'([BoxTop ()]
|
||||
[ChannelTop ()]
|
||||
[ClassTop ()]
|
||||
[Continuation-Mark-KeyTop ()]
|
||||
[Error ()]
|
||||
[HashtableTop ()]
|
||||
[MPairTop ()]
|
||||
[Prompt-TagTop ()]
|
||||
[StructTypeTop ()]
|
||||
[ThreadCellTop ()]
|
||||
[Univ ()]
|
||||
[VectorTop ()]
|
||||
|
||||
[CustodianBox (#:co)]
|
||||
[Ephemeron (#:co)]
|
||||
[Evt (#:co)]
|
||||
[Future (#:co)]
|
||||
[Instance (#:co)]
|
||||
[Promise (#:co)]
|
||||
[Set (#:co)]
|
||||
[StructTop (#:co)]
|
||||
[StructType (#:co)]
|
||||
[Syntax (#:co)]
|
||||
[Pair (#:co #:co)]
|
||||
[Sequence ((#:listof #:co))]
|
||||
[Function ((#:listof #:co))]
|
||||
|
||||
[Param (#:contra #:co)]
|
||||
|
||||
[Continuation-Mark-Keyof (#:inv)]
|
||||
[Box (#:inv)]
|
||||
[Channel (#:inv)]
|
||||
[ThreadCell (#:inv)]
|
||||
[Vector (#:inv)]
|
||||
[Hashtable (#:inv #:inv)]
|
||||
[MPair (#:inv #:inv)]
|
||||
[Prompt-Tagof (#:inv #:inv)]
|
||||
[HeterogeneousVector ((#:listof #:inv))]
|
||||
|
||||
;; Non Types
|
||||
[Result (#:co #:co #:co)]
|
||||
[Values ((#:listof #:co))]
|
||||
[AnyValues ()]
|
||||
[top-arr ()]))
|
||||
|
||||
(begin-for-syntax
|
||||
(define-syntax-class type-name
|
||||
#:attributes (pred? matcher: maker)
|
||||
(pattern t:id
|
||||
#:with pred? (format-id #'t "~a?" #'t)
|
||||
#:with matcher: (format-id #'t "~a:" #'t)
|
||||
#:with maker (format-id #'t "make-~a" #'t))))
|
||||
|
||||
(begin-for-syntax
|
||||
(define-syntax-class type-variance
|
||||
#:attributes (sym)
|
||||
(pattern #:co #:with sym 'co)
|
||||
(pattern #:inv #:with sym 'inv)
|
||||
(pattern #:contra #:with sym 'contra))
|
||||
|
||||
(define-syntax-class type-field
|
||||
(pattern var:type-variance)
|
||||
(pattern (#:listof var:type-variance))))
|
||||
|
||||
|
||||
|
||||
(define-syntax (gen-structural? stx)
|
||||
(syntax-parse structural-reps
|
||||
[([type:type-name (field:type-field ...)] ...)
|
||||
#'(lambda (t)
|
||||
(or (type.pred? t) ...))]))
|
||||
|
||||
;; Returns true if the type/filter/object supports structural operations.
|
||||
(define structural? (gen-structural?))
|
||||
|
||||
|
||||
(define-syntax (gen-structural-map stx)
|
||||
(syntax-parse stx
|
||||
[(_ input-type:id recur-f:id)
|
||||
(define-syntax-class type-field*
|
||||
#:attributes (recur)
|
||||
(pattern var:type-variance
|
||||
#:with recur #'(λ (t) (recur-f t 'var.sym)))
|
||||
(pattern (#:listof var:type-variance)
|
||||
#:with recur #'(λ (ts) (for/list ([t (in-list ts)]) (recur-f t 'var.sym)))))
|
||||
|
||||
(define-syntax-class type-clause
|
||||
#:attributes (match-clause)
|
||||
(pattern [type:type-name (field:type-field* ...)]
|
||||
#:with (field-pat ...) (generate-temporaries #'(field ...))
|
||||
#:with match-clause
|
||||
#'[(type.matcher: field-pat ...)
|
||||
(type.maker (field.recur field-pat) ...)]))
|
||||
|
||||
(syntax-parse structural-reps
|
||||
[(:type-clause ...)
|
||||
#'(match input-type match-clause ...)])]))
|
||||
|
||||
;; Rep? (-> Rep? (or/c 'co 'contra 'inv) Rep?) -> Rep?
|
||||
;; Calls `f` on each sub-type with the corresponding variance of the sub-type and combines the results
|
||||
;; using the type constructor of the input type
|
||||
(define (structural-map t f)
|
||||
(gen-structural-map t f))
|
Loading…
Reference in New Issue
Block a user