Skip to content

Commit 381b3c4

Browse files
authored
Merge pull request #69 from iitalics/pretty-arrow-string
Pretty-print infix types (such as "->") with infix notation
2 parents fec564d + c0ce079 commit 381b3c4

File tree

5 files changed

+68
-39
lines changed

5 files changed

+68
-39
lines changed

hackett-lib/hackett/private/adt.rkt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@
3030
(provide (contract-out [struct type-constructor ([type type?]
3131
[arity exact-nonnegative-integer?]
3232
[data-constructors (listof identifier?)]
33-
[fixity operator-fixity?])]
33+
[fixity (or/c operator-fixity? #f)])]
3434
[struct data-constructor ([macro procedure?]
3535
[type type?]
3636
[make-match-pat procedure?]
37-
[fixity operator-fixity?])])))
37+
[fixity (or/c operator-fixity? #f)])])))
3838

3939
(begin-for-syntax
4040
(define-splicing-syntax-class type-constructor-spec
@@ -472,7 +472,7 @@
472472
; quantify the type using the type variables in τ, then evaluate the type
473473
#:with τ_con:type #'(forall [τ.arg ...] τ_con_unquantified)
474474
#:with [field ...] (generate-temporaries (attribute constructor.arg))
475-
#:with fixity-expr (preservable-property->expression (or (attribute constructor.fixity) 'left))
475+
#:with fixity (attribute constructor.fixity)
476476
#`(begin-
477477
(define-values- [] τ_con.residual)
478478
; check if the constructor is nullary or not
@@ -488,7 +488,7 @@
488488
(make-typed-var-transformer #'tag- (quote-syntax τ_con.expansion))
489489
(quote-syntax τ_con.expansion)
490490
(match-lambda [(list) #'(app force- (==- tag-))])
491-
fixity-expr)))
491+
'fixity)))
492492
; if it isn’t, define a constructor function
493493
#`(splicing-local- [(struct- tag- (field ...) #:transparent
494494
#:reflection-name 'constructor.tag)
@@ -502,21 +502,21 @@
502502
(quote-syntax τ_con.expansion)
503503
(match-lambda [(list field ...)
504504
#`(app force- (tag- #,field ...))])
505-
fixity-expr)))))])
505+
'fixity)))))])
506506

507507
(define-syntax-parser data
508508
[(_ τ:type-constructor-spec constructor:data-constructor-spec ...
509509
{~optional
510510
{~seq #:deriving [{~type {~var class-id (class-id #:require-deriving-transformer? #t)}} ...]}
511511
#:defaults ([[class-id 1] '()])})
512512
#:with [τ*:type-constructor-spec] (type-namespace-introduce #'τ)
513-
#:with fixity-expr (preservable-property->expression (or (attribute τ.fixity) 'left))
513+
#:with fixity (attribute τ.fixity)
514514
#`(begin-
515515
(define-syntax- τ*.tag (type-constructor
516516
#'(#%type:con τ*.tag)
517517
'#,(attribute τ*.len)
518518
(list #'constructor.tag ...)
519-
fixity-expr))
519+
'fixity))
520520
(define-data-constructor τ* constructor) ...
521521
(derive-instance class-id τ*.tag) ...)])
522522

hackett-lib/hackett/private/base.rkt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
syntax/parse/define
1616

1717
(for-syntax hackett/private/infix
18-
(rename-in hackett/private/typecheck [-> ->/prefix])
18+
hackett/private/typecheck
1919
hackett/private/util/list
2020
hackett/private/util/stx))
2121

@@ -39,8 +39,6 @@
3939
(syntax-property 'disappeared-use (list (syntax-local-introduce #'op-)
4040
(syntax-local-introduce #'colon))))])
4141

42-
(define-syntax -> (infix-operator-impl #'->/prefix 'right))
43-
4442
(begin-for-syntax
4543
;; -------------------------------------------------------------------------------------------------
4644
;; inference/checking + erasure/expansion

hackett-lib/hackett/private/infix.rkt

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,37 +14,46 @@
1414
syntax/parse/class/local-value)
1515

1616
(provide (contract-out
17-
[prop:infix-operator (struct-type-property/c (-> any/c operator-fixity?))]
18-
[struct infix-operator-impl ([id identifier?] [fixity operator-fixity?])])
19-
operator-fixity? infix-operator? infix-operator-fixity
20-
infix-operator fixity-annotation indirect-infix-definition)
17+
[prop:infix-operator (struct-type-property/c (-> any/c (or/c operator-fixity? #f)))]
18+
[infix-operator-fixity (-> infix-operator? operator-fixity?)]
19+
[make-infix-variable-like-transformer
20+
(-> (or/c syntax? (-> syntax? syntax?)) (or/c operator-fixity? #f) (-> syntax? syntax?))]
21+
[indirect-infix-definition (-> syntax? (or/c operator-fixity? #f) syntax?)])
22+
operator-fixity? infix-operator? infix-operator fixity-annotation)
2123

2224
(define operator-fixity?
2325
(flat-named-contract
2426
'operator-fixity?
2527
(or/c 'left 'right)))
2628

27-
(define-values [prop:infix-operator infix-operator? infix-operator-fixity-procedure]
29+
(define-values [prop:infix-operator has-prop:infix-operator? infix-operator-fixity-procedure]
2830
(make-struct-type-property 'infix-operator))
2931

3032
(define (infix-operator-fixity operator)
3133
((infix-operator-fixity-procedure operator) operator))
34+
35+
(define (infix-operator? x)
36+
(and (has-prop:infix-operator? x)
37+
(operator-fixity? (infix-operator-fixity x))))
3238

33-
(struct infix-operator-impl (id fixity)
34-
#:transparent
35-
#:property prop:procedure
36-
(λ (operator stx) ((make-variable-like-transformer (infix-operator-impl-id operator)) stx))
39+
(struct infix-variable-like-transformer (procedure fixity)
40+
#:property prop:procedure (struct-field-index procedure)
3741
#:property prop:infix-operator
38-
(λ (operator) (infix-operator-impl-fixity operator)))
42+
(λ (operator) (infix-variable-like-transformer-fixity operator)))
43+
44+
(define (make-infix-variable-like-transformer expr fixity)
45+
(let ([proc (make-variable-like-transformer expr)])
46+
(if fixity (infix-variable-like-transformer proc fixity) proc)))
3947

40-
(define-syntax-class infix-operator
48+
(define-syntax-class (infix-operator #:default-fixity [default-fixity 'left])
4149
#:description #f
4250
#:commit
4351
#:attributes [fixity]
4452
[pattern {~var op (local-value infix-operator?)}
4553
#:attr fixity (infix-operator-fixity (attribute op.local-value))]
4654
[pattern _:expr
47-
#:attr fixity 'left])
55+
#:when default-fixity
56+
#:attr fixity default-fixity])
4857

4958
(define-splicing-syntax-class fixity-annotation
5059
#:description "fixity annotation"
@@ -61,10 +70,9 @@
6170
; > (indirect-infix-definition #'(define :: cons) 'right)
6271
; #'(begin
6372
; (define ::1 cons)
64-
; (define-syntax :: (infix-operator-impl #'::1 'right)))
73+
; (define-syntax :: (infix-variable-like-transformer #'::1 'right)))
6574
;
66-
(define/contract (indirect-infix-definition stx fixity)
67-
(-> syntax? (or/c operator-fixity? #f) syntax?)
75+
(define (indirect-infix-definition stx fixity)
6876
(if fixity
6977
(syntax-parse stx
7078
#:context 'indirect-infix-definition
@@ -73,5 +81,5 @@
7381
#:with fixity-expr (preservable-property->expression fixity)
7482
#'(begin
7583
(d id- expr)
76-
(define-syntax id (infix-operator-impl #'id- fixity-expr)))])
84+
(define-syntax id (make-infix-variable-like-transformer #'id- fixity-expr)))])
7785
stx))

hackett-lib/hackett/private/type-language.rkt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
syntax/parse/experimental/template
1616
threading
1717

18+
hackett/private/infix
1819
hackett/private/util/stx)
1920
syntax/parse/define)
2021

@@ -307,17 +308,19 @@
307308
({~literal #%type:con} {~literal #,con-id}))
308309
pat ...))])))))
309310

310-
(define-simple-macro (define-base-type name:id)
311+
(define-simple-macro (define-base-type name:id {~optional fixity-ann:fixity-annotation})
311312
#:with {~var ~name} (format-id #'name "~~~a" #'name #:source #'name #:props #'name)
312313
; Ensure that the binding does not have either the type or the value scope on it. Otherwise, if the
313314
; type appears in a fully-expanded type or value, and the namespace on the resulting piece of syntax
314315
; is flipped, the identifier can become unbound.
315316
#:with name- (datum->syntax #'here (syntax-e #'name) #'name)
317+
#:with fixity (attribute fixity-ann.fixity)
316318
(begin
317-
(define-syntax name- (make-variable-like-transformer
319+
(define-syntax name- (make-infix-variable-like-transformer
318320
(λ (name-id)
319-
#`(#%type:con #,(replace-stx-loc (quote-syntax name-) name-id)))))
320-
(define-syntax name (make-rename-transformer #'name-))
321+
#`(#%type:con #,(replace-stx-loc (quote-syntax name-) name-id)))
322+
'fixity))
323+
(define-syntax name (make-rename-transformer (quote-syntax name-)))
321324
(begin-for-syntax
322325
(define-syntax ~name (make-type-con-pattern-expander (quote-syntax name))))))
323326

@@ -328,7 +331,7 @@
328331
; handled specially by the typechecker in order to implement higher-rank polymorphism, so they are
329332
; defined here.
330333

331-
(define-base-type ->)
334+
(define-base-type -> #:fixity right)
332335

333336
(begin-for-syntax
334337
(define-syntax-class nested-->s

hackett-lib/hackett/private/typecheck.rkt

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
racket/function
2222
racket/list
2323
racket/match
24+
racket/string
2425
racket/syntax
2526
racket/stxparam-exptime
2627
syntax/id-table
@@ -30,6 +31,7 @@
3031
syntax/parse/experimental/template
3132
threading
3233

34+
hackett/private/infix
3335
hackett/private/util/list
3436
hackett/private/util/stx)
3537

@@ -111,26 +113,44 @@
111113

112114
(define/contract (type->string t)
113115
(-> type? string?)
114-
(format "~a"->datum t)))
116+
(~a (type->datum t)))
115117

116-
(define/contract τ->datum
118+
(define/contract type->datum
117119
(-> type? any/c)
118120
(syntax-parser
119-
#:context 'τ->datum
121+
#:context 'type->string
120122
#:literal-sets [type-literals]
121123
[x:id (syntax-e #'x)]
122124
[(#%type:wobbly-var x^) (string->symbol (format "~a^" (syntax-e #'x^)))]
123125
[(#%type:rigid-var x^) (syntax-e #'x^)]
124126
[(#%type:con name) (syntax-e #'name)]
125-
[{~#%type:app+ t ...} (map τ->datum (attribute t))]
127+
[{~#%type:app+ (#%type:con {~var op (infix-operator #:default-fixity #f)}) _ _}
128+
(infix-type->string #'op (attribute op.fixity) this-syntax)]
129+
[{~#%type:app+ t ...} (map type->datum (attribute t))]
126130
[{~#%type:forall* [x ...+] {~#%type:qual* [constr ...+] t}}
127131
`(forall ,(map syntax-e (attribute x))
128-
,@(map τ->datum (attribute constr))
129-
=> ,(τ->datum #'t))]
132+
,@(map type->datum (attribute constr))
133+
=> ,(type->datum #'t))]
130134
[{~#%type:forall* [x ...+] t}
131-
`(forall ,(map syntax-e (attribute x)) ,(τ->datum #'t))]
135+
`(forall ,(map syntax-e (attribute x)) ,(type->datum #'t))]
132136
[{~#%type:qual* [constr ...+] t}
133-
`(=> ,(map τ->datum (attribute constr)) ,(τ->datum #'t))]))
137+
`(=> ,(map type->datum (attribute constr)) ,(type->datum #'t))]))
138+
139+
(define/contract (infix-type->string op-id fixity t0)
140+
(-> identifier? operator-fixity? type? string?)
141+
(define traverse
142+
(syntax-parser
143+
#:literal-sets [type-literals]
144+
[{~#%type:app* (#%type:con op) t s}
145+
#:when (free-identifier=? #'op op-id)
146+
(case fixity
147+
[(left) (snoc (traverse #'t) #'s)]
148+
[(right) (cons #'t (traverse #'s))])]
149+
[t (list #'t)]))
150+
(string-join (map type->string (traverse t0))
151+
(format " ~a " (syntax-e op-id))
152+
#:before-first "{"
153+
#:after-last "}"))
134154

135155
;; ---------------------------------------------------------------------------------------------------
136156
;; type contexts

0 commit comments

Comments
 (0)