implement stlc+box and stlc+effect with typed-lang-builder

This commit is contained in:
AlexKnauth 2016-06-20 15:14:20 -04:00
parent 3a97efcb24
commit c8ff0afa02
6 changed files with 174 additions and 24 deletions

View File

@ -12,9 +12,9 @@
;; - ref deref :=
(begin-for-syntax
(define (add-news e locs) (syntax-property e 'new locs))
(define (add-assigns e locs) (syntax-property e 'assign locs))
(define (add-derefs e locs) (syntax-property e 'deref locs))
(define (add-news e locs) (syntax-property e 'ν locs))
(define (add-assigns e locs) (syntax-property e ':= locs))
(define (add-derefs e locs) (syntax-property e '! locs))
(define (add-effects e new-locs assign-locs deref-locs)
(add-derefs
(add-assigns
@ -27,16 +27,16 @@
(local-expand (if (null? vs) e #`(stlc+box:λ #,vs #,e)) 'expression null)
tag)
null))
(define (get-new-effects e [vs '()]) (get-effects e 'new vs))
(define (get-assign-effects e [vs '()]) (get-effects e 'assign vs))
(define (get-deref-effects e [vs '()]) (get-effects e 'deref vs))
(define (get-new-effects e [vs '()]) (get-effects e 'ν vs))
(define (get-assign-effects e [vs '()]) (get-effects e ':= vs))
(define (get-deref-effects e [vs '()]) (get-effects e '! vs))
(define (print-effects e)
(printf "expr ~a\n" (syntax->datum e))
(define e+ (local-expand e 'expression null))
(printf "new locs: ~a\n" (syntax-property e+ 'new))
(printf "deref locs: ~a\n" (syntax-property e+ 'deref))
(printf "assign locs: ~a\n" (syntax-property e+ 'assign)))
(printf "new locs: ~a\n" (syntax-property e+ 'ν))
(printf "deref locs: ~a\n" (syntax-property e+ '!))
(printf "assign locs: ~a\n" (syntax-property e+ ':=)))
(define (loc-union locs1 locs2)
(cond
@ -128,11 +128,11 @@
(stx-append #'ds1 #'ds2))])
;(define-typed-syntax ref
; [(_ e)
; (syntax-property #'(stlc+box:ref e) 'new (set (syntax-position stx)))])
; (syntax-property #'(stlc+box:ref e) 'ν (set (syntax-position stx)))])
;(define-typed-syntax deref
; [(_ e)
; (syntax-property #'(stlc+box:deref e) 'deref (set (syntax-position stx)))])
; (syntax-property #'(stlc+box:deref e) '! (set (syntax-position stx)))])
;(define-typed-syntax :=
; [(_ e_ref e)
; (syntax-property #'(stlc+box::= e_ref e) 'assign (set (syntax-position stx)))])
; (syntax-property #'(stlc+box::= e_ref e) ':= (set (syntax-position stx)))])

View File

@ -41,15 +41,15 @@
;; for checking properties other than types
(define-syntax (check-props stx)
(syntax-parse stx #:datum-literals (: ->)
[(_ prop e : v ... (~optional (~seq (~or ->) v2) #:defaults ([v2 #'e])))
[(_ prop e : v (~optional (~seq (~or ->) v2) #:defaults ([v2 #'e])))
#:with props (or (syntax-property (expand/df #'e) (syntax->datum #'prop))
#'())
#:fail-unless (set=? (apply set (syntax->datum #'(v ...)))
(apply set (syntax->datum #'props)))
#:fail-unless (equal? (syntax->datum #'v)
(syntax->datum #'props))
(format
"Expression ~a [loc ~a:~a:~a] does not have prop ~a, actual: ~a"
(syntax->datum #'e) (syntax-line #'e) (syntax-column #'e) (syntax-position #'e)
(syntax->datum #'(v ...)) (syntax->datum #'props))
(syntax->datum #'v) (syntax->datum #'props))
(syntax/loc stx (check-equal? e v2))]))
(define-syntax (check-not-type stx)

View File

@ -1,4 +1,4 @@
#lang s-exp "../stlc+box.rkt"
#lang s-exp "../typed-lang-builder/stlc+box.rkt"
(require "rackunit-typechecking.rkt")
(define x (ref 10))
@ -26,11 +26,11 @@
(typecheck-fail
(deref 1)
#:with-msg
"Expected expression 1 to have Ref type, got: Int")
"Expected Ref type, got: Int")
(typecheck-fail
(:= 1 1)
#:with-msg
"Expected expression 1 to have Ref type, got: Int")
"Expected Ref type, got: Int")
;; previous tests: ------------------------------------------------------------
(typecheck-fail (cons 1 2))

View File

@ -1,10 +1,10 @@
#lang s-exp "../stlc+effect.rkt"
#lang s-exp "../typed-lang-builder/stlc+effect.rkt"
(require "rackunit-typechecking.rkt")
(check-props new (ref 11) : 90)
(check-props deref (deref (ref 11)) : 124)
(check-props new (deref (ref 11)) : 172)
(check-props new ((λ ([x : Int]) (ref x)) 21) : 222)
(check-props ν (ref 11) : '(107))
(check-props ! (deref (ref 11)) : '(141))
(check-props ν (deref (ref 11)) : '(190))
(check-props ν ((λ ([x : Int]) (ref x)) 21) : '(241))
(define x (ref 10))
(check-type x : (Ref Int))

View File

@ -0,0 +1,32 @@
#lang macrotypes/tapl/typed-lang-builder
(extends "stlc+cons.rkt")
;; Simply-Typed Lambda Calculus, plus mutable references
;; Types:
;; - types from stlc+cons.rkt
;; - Ref constructor
;; Terms:
;; - terms from stlc+cons.rkt
;; - ref deref :=
(define-type-constructor Ref)
(define-typed-syntax ref
[(ref e)
[ [[e e-] (: τ)]]
--------
[ [[_ (box- e-)] (: (Ref τ))]]])
(define-typed-syntax deref
[(deref e)
[ [[e e-] (: (~Ref τ))]]
--------
[ [[_ (unbox- e-)] (: τ)]]])
(define-typed-syntax := #:literals (:=)
[(:= e_ref e)
[ [[e_ref e_ref-] (: (~Ref τ))]]
[ [[e e-] (: τ)]]
--------
[ [[_ (set-box!- e_ref- e-)] (: Unit)]]])

View File

@ -0,0 +1,118 @@
#lang macrotypes/tapl/typed-lang-builder
(extends "stlc+box.rkt" #:except ref deref := #%app λ)
(provide (for-syntax get-new-effects))
;; Simply-Typed Lambda Calculus, plus mutable references
;; Types:
;; - types from stlc+cons.rkt
;; - Ref constructor
;; Terms:
;; - terms from stlc+cons.rkt
;; - ref deref :=
(define-syntax-rule (locs loc ...)
'(loc ...))
(begin-for-syntax
(define-syntax ~locs
(pattern-expander
(syntax-parser
[(locs loc:id ...)
#:with tmp (generate-temporary 'locs)
#'(~and tmp
(~parse ((~literal quote) (loc ...))
(stx-or #'tmp #'(quote ()))))])))
(define (add-news e locs) (assign-type e #:tag 'ν locs))
(define (add-assigns e locs) (assign-type e #:tag ':= locs))
(define (add-derefs e locs) (assign-type e #:tag '! locs))
(define (add-effects e new-locs assign-locs deref-locs)
(add-derefs
(add-assigns
(add-news e new-locs)
assign-locs)
deref-locs))
(define (get-effects e tag)
(syntax-property e tag))
(define (get-new-effects e) (get-effects e 'ν))
(define (get-assign-effects e) (get-effects e ':=))
(define (get-deref-effects e) (get-effects e '!))
(define (print-effects e)
(printf "expr ~a\n" (syntax->datum e))
(define e+ (local-expand e 'expression null))
(printf "new locs: ~a\n" (syntax-property e+ 'ν))
(printf "deref locs: ~a\n" (syntax-property e+ '!))
(printf "assign locs: ~a\n" (syntax-property e+ ':=)))
(define (stx-cons a b)
(datum->syntax #f (cons a b)))
(define (stx-truth? a)
(and a (not (and (syntax? a) (false? (syntax-e a))))))
(define (stx-or a b)
(cond [(stx-truth? a) a]
[else b])))
(define-typed-syntax effect:#%app #:export-as #%app
[(_ efn e ...)
[ [[efn e_fn-]
(: ty_fn ν (~locs fns ...) := (~locs fas ...) ! (~locs fds ...))
(ν (~locs tyns ...) := (~locs tyas ...) ! (~locs tyds ...))]]
[#:with (~→ τ_in ... τ_out) #'ty_fn]
[ [[e e_arg-] (: τ_arg ν (~locs ns ...) := (~locs as ...) ! (~locs ds ...))] ...]
[#:fail-unless (stx-length=? #'(τ_arg ...) #'(τ_in ...))
"wrong number of arguments"]
[τ_arg τ⊑ τ_in] ...
--------
[ [[_ (#%app- e_fn- e_arg- ...)]
(: τ_out
ν (locs fns ... tyns ... ns ... ...)
:= (locs fas ... tyas ... as ... ...)
! (locs fds ... tyds ... ds ... ...))]]])
(define-typed-syntax λ
[(λ bvs:type-ctx e)
[() ([bvs.x : bvs.type x-] ...)
[[e e-]
(: τ_res ν (~locs ns ...) := (~locs as ...) ! (~locs ds ...))]]
--------
[ [[_ (λ- (x- ...) e-)]
(: #,(add-effects #'( bvs.type ... τ_res)
#'(locs ns ...)
#'(locs as ...)
#'(locs ds ...)))]]])
(define-type-constructor Ref)
(define-typed-syntax ref
[(ref e)
[ [[e e-] (: τ ν (~locs ns ...) := (~locs as ...) ! (~locs ds ...))]]
--------
[ [[_ (box- e-)]
(: (Ref τ)
ν (locs #,(syntax-position stx) ns ...)
:= (locs as ...)
! (locs ds ...))]]])
(define-typed-syntax deref
[(deref e)
[ [[e e-] (: (~Ref ty) ν (~locs ns ...) := (~locs as ...) ! (~locs ds ...))]]
--------
[ [[_ (unbox- e-)]
(: ty
ν (locs ns ...)
:= (locs as ...)
! (locs #,(syntax-position stx) ds ...))]]])
(define-typed-syntax := #:literals (:=)
[(:= e_ref e)
[ [[e_ref e_ref-] (: (~Ref ty1) ν (~locs ns1 ...) := (~locs as1 ...) ! (~locs ds1 ...))]]
[ [[e e-] (: ty2 ν (~locs ns2 ...) := (~locs as2 ...) ! (~locs ds2 ...))]]
[ty1 τ⊑ ty2]
--------
[ [[_ (set-box!- e_ref- e-)]
(: Unit
ν (locs ns1 ... ns2 ...)
:= (locs #,(syntax-position stx) as1 ... as2 ...)
! (locs ds1 ... ds2 ...))]]])