www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

phc-adt-choices.scrbl (5239B)


      1 #lang hyper-literate typed/racket
      2 @(require scribble-enhanced/doc)
      3 @doc-lib-setup
      4 
      5 @title[#:style manual-doc-style
      6        #:tag "choices"
      7        #:tag-prefix "phc-adt/choices"]{Somewhat outdated
      8  overview of the implementation choices for structures, graphs and passes}
      9 
     10 @(chunks-toc-prefix
     11   '("(lib phc-adt/scribblings/phc-adt-implementation.scrbl)"
     12     "phc-adt/choices"))
     13 
     14 @section[#:tag "type-system|structures"]{Structures}
     15 
     16 Structures are represented as lists of key/value pairs.
     17 @note{We need lists and can't use vectors (or hash tables) because the latter
     18  are mutable in @code|{typed/racket}|, and the typing system has no guarantee
     19  that accessing the same element twice will yield the same value (so occurence
     20  typing can't narrow the type in branches of conditionnals).}
     21 @note{Actually, we can use structs (they are immutable by default, and the
     22  occurrence typing knows that). There are two problems with them. The first
     23  problem is that we cannot have subtyping (although knowing all the structs
     24  used in the program means we can just filter them and use a
     25  @racket[(U S1 S2 …)]. The second problem is that in order to declare the
     26  structs, we would need to be in a define-like environment (therefore making
     27  anonymous structure types problematic). The second problem can be solved in
     28  the same way as the first: if all the structs are known in advance, we can
     29  pre-declare them in a shared file.}
     30 
     31 @chunk[<example-simple-structure>
     32        (define-type abc (List (Pairof 'a Number)
     33                               (Pairof 'b String)
     34                               (Pairof 'c (U 'x 'y))))
     35        
     36        (: make-abc (→ Number String (U 'x 'y) abc))
     37        (define (make-abc a b c)
     38          (list (cons 'a a) (cons 'b b) (cons 'c c)))
     39        (make-abc 1 "b" 'x)]
     40 
     41 Occurrence typing works:
     42 
     43 @chunk[<example-simple-structure-occurrence>
     44        (: f (→ abc (U 'x #f)))
     45        (define (f v)
     46          (if (eq? 'x (cdr (cddr v)))
     47              (cdr (cddr v))
     48              #f))]
     49 
     50 @section{Passes, subtyping and tests}
     51 
     52 Below is the definition of a function which works on
     53 @tc[(structure [a Number] [b String] [c Boolean])], and returns the same
     54 structure extended with a field @tc[[d Number]], but is only concerned with
     55 fields @tc[a] and @tc[c], so tests don't need to provide a value for @tc[b].
     56 
     57 @chunk[<example-pass-which-extends-input>
     58        (: pass-calc-d (∀ (TB) (→ (List (Pairof 'a Number)
     59                                        (Pairof 'b TB)
     60                                        (Pairof 'c Boolean))
     61                                  (List (Pairof 'a Number)
     62                                        (Pairof 'b TB)
     63                                        (Pairof 'c Boolean)
     64                                        (Pairof 'd Number)))))
     65        (define (pass-calc-d v)
     66          (list (car v) ; a
     67                (cadr v) ; b
     68                (caddr v) ; c
     69                (cons 'd (+ (cdar v) (if (cdaddr v) 0 1)))))]
     70 
     71 The example above can be called to test it with a dummy value for @tc[b]:
     72 
     73 @chunk[<example-pass-which-extends-input>
     74        (pass-calc-d '((a . 1) (b . no-field) (c . #t)))]
     75 
     76 But when called with a proper value for @tc[b], we get back the original
     77 string as expected, and the type is correct:
     78 
     79 @chunk[<example-pass-which-extends-input>
     80        (ann (pass-calc-d '((a . 1) (b . "some string") (c . #t)))
     81             (List (Pairof 'a Number)
     82                   (Pairof 'b String)
     83                   (Pairof 'c Boolean)
     84                   (Pairof 'd Number)))]
     85 
     86 If the pass should be able to work on multiple graph types (each being a subtype
     87 containing a common subset of fields), then it should be easy to mark it as a
     88 @tc[case→] function. It is probably better to avoid too permissive subtyping,
     89 otherwise, imagine we have
     90 a pass which removes @tc[Addition]s and @tc[Substraction]s from an AST, and
     91 replaces them with a single @tc[Arithmetic] node type. If we have full duck
     92 typing, we could call it with @tc[Addition]s and @tc[Substraction] hidden in
     93 fields it does not know about, and so it would fail to replace them. Also, it
     94 could be called with an already-processed AST which already contains just
     95 @tc[Arithmetic] node types, which would be a bug most likely. Therefore,
     96 explicitly specifying the graph type on which the passes work seems a good
     97 practice. Some parts can be collapsed easily into a @tc[∀] type @tc[T], when
     98 we're sure there shouldn't be anything that interests us there.
     99 
    100 @section{Graphs}
    101 
    102 In order to be able to have cycles, while preserving the benefits of
    103 occurrence typing, we need to make sure that from the type system's point of
    104 view, accessing a successor node twice will return the same value each time.
    105 
    106 The easiest way for achieving this is to wrap the to-be-created value inside a
    107 @tc[Promise]. Occurrence typing works on those:
    108 
    109 @chunk[<test-promise-occurence-typing>
    110        (: test-promise-occurence (→ (Promise (U 'a 'b)) (U 'a #f)))
    111        (define (test-promise-occurence p)
    112          (if (eq? (force p) 'a)
    113              (force p)
    114              #f))]
    115 
    116 @section{Conclusion}
    117 
    118 @chunk[<*>
    119        <example-simple-structure>
    120        <example-simple-structure-occurrence>
    121          
    122        <example-pass-which-extends-input>
    123          
    124        <test-promise-occurence-typing>]