extend define-tycon with "get"- extract matched type by pat var name

This commit is contained in:
Stephen Chang 2015-07-30 14:12:34 -04:00
parent 9973e1c705
commit b687cffb0a
4 changed files with 52 additions and 20 deletions

View File

@ -1,7 +1,8 @@
#lang racket/base
(require "typecheck.rkt")
(require "stlc.rkt")
(provide (all-from-out "stlc.rkt"))
(extends "stlc.rkt" #:impl-uses ())
;(require "stlc.rkt")
;(provide (all-from-out "stlc.rkt"))
(provide (rename-out [datum/tc #%datum]))
;; Simply-Typed Lambda Calculus, plus numeric literals and primitives

View File

@ -48,7 +48,9 @@
(define current-type=? (make-parameter type=?))
(current-typecheck-relation type=?))
(define-type-constructor ( τ_in ... τ_out))
(define-type-constructor ( τ_in ... τ_out)
#:declare τ_in type
#:declare τ_out type)
(define-syntax (λ/tc stx)
(syntax-parse stx

View File

@ -30,9 +30,10 @@
#:with-msg "not a valid type: Bool")
(typecheck-fail (λ ([x : Bool]) x)
#:with-msg "not a valid type: Bool")
(typecheck-fail (λ ([f : Int]) (f 1 2))
#:with-msg
"Expected type with pattern: \\(→ τ_in ... τ_out\\), got: Int")
(typecheck-fail
(λ ([f : Int]) (f 1 2))
#:with-msg
"Expected type of expression f to match pattern \\(→ τ_in ... τ_out\\), got: Int")
(check-type (λ ([f : ( Int Int Int)] [x : Int] [y : Int]) (f x y))
: ( ( Int Int Int) Int Int Int))

View File

@ -3,7 +3,7 @@
(for-syntax (except-in racket extends)
syntax/parse racket/syntax syntax/stx
"stx-utils.rkt")
(for-meta 2 racket/base syntax/parse)
(for-meta 2 racket/base syntax/parse racket/syntax)
racket/provide)
(provide
(for-syntax (all-defined-out)) (all-defined-out)
@ -39,7 +39,7 @@
(define-syntax extends
(syntax-parser
[(_ base-lang
(~optional (~seq #:use (x ...)) #:defaults ([(x 1) null])))
(~optional (~seq #:impl-uses (x ...)) #:defaults ([(x 1) null])))
#:with pre (generate-temporary)
#:with pre: (format-id #'pre "~a:" #'pre)
#'(begin
@ -122,18 +122,25 @@
(define-syntax define-type-constructor
(syntax-parser
[(_ (τ:id . pat))
[(_ (τ:id . pat)
(~optional (~seq #:lits (lit ...)) #:defaults ([(lit 1) null]))
decls ...
#;(~optional (~seq (~seq #:decl tvar (~datum as) cls) ...)
#:defaults ([(tvar 1) null][(cls 1) null])))
#:with τ-match (format-id #'τ "~a-match" #'τ)
#:with τ? (format-id #'τ "~a?" #'τ)
#:with τ-get (format-id #'τ "~a-get" #'τ)
#:with τ-match+erase (format-id #'τ "~a-match+erase" #'τ)
#:with pat-class (generate-temporary #'τ) ; syntax-class name
#:with tycon (generate-temporary #'τ) ; need a runtime id for expansion
#'(begin
#`(begin
(define lit void) ...
(provide τ)
(begin-for-syntax
(define-syntax-class pat-class
(define-syntax-class pat-class #:literals (lit ...)
;; dont check is-type? here; should already be types
;; only need to check is-type? for user-entered types
;; only check is-type? for user-entered types, eg tycon call
;; thus, dont include decls here, only want shape
(pattern pat))
(define (τ-match ty)
(or (match-type ty tycon pat-class)
@ -146,17 +153,38 @@
;; expression version of τ-match
(define (τ-match+erase e)
(syntax-parse (infer+erase e)
[(e- τ)
#:with τ_matched (τ-match #'τ)
#'(e- τ_matched)])))
[(e- ty)
#:with τ_matched/#f (match-type #'ty tycon pat-class)
#:fail-unless (syntax-e #'τ_matched/#f)
(format
"~a (~a:~a): Expected type of expression ~a to match pattern ~a, got: ~a"
(syntax-source e) (syntax-line e) (syntax-column e)
(syntax->datum e) (type->str (quote-syntax (τ . pat))) (type->str #'ty))
#'(e- τ_matched/#f)]))
;; get syntax bound to specific pat var (as declared in def-tycon)
(define-syntax (τ-get stx)
(syntax-parse stx #:datum-literals (from)
[(_ attr from ty)
#:with args (generate-temporary)
#:with args.attr (format-id #'args "~a.~a" #'args #'attr)
#'(syntax-parse ((current-type-eval) ty)
[((~literal #%plain-type) ((~literal #%plain-app) t . args))
#:declare args pat-class ; check shape of arguments
#:fail-unless (typecheck? #'t #'tycon) ; check tycons match
(format "Type error: expected ~a type, got ~a"
(type->str #'τ) (type->str ty))
(attribute args.attr)])])))
(define tycon (λ _ (raise (exn:fail:type:runtime
(format "~a: Cannot use type at run time" 'τ)
(current-continuation-marks)))))
(define-syntax (τ stx)
(syntax-parse stx
[(_ . pat) ; first check shape
#:with (~! (~var t type) (... ...)) #'pat ; then check for valid types
#'(#%type (tycon . pat))]
(syntax-parse stx #:literals (lit ...)
[(_ . (~and pat !~ args)) ; first check shape
; this inner syntax-parse gets the ~! to register
; otherwise, apparently #:declare's get subst into pat (before ~!)
(syntax-parse #'args
[pat #,@#'(decls ...) ; then check declarations (eg, valid type)
#'(#%type (tycon . args))])]
[_ (type-error #:src stx
#:msg "Improper usage of type constructor ~a: ~a, expected pattern ~a"
#'τ stx (quote-syntax (τ . pat)))])))]))
@ -258,7 +286,7 @@
;; macro for nicer syntax
(define-syntax ( stx)
(syntax-parse stx #:datum-literals (:)
[(_ e : τ) #'(assign-type #'e #'τ)]
[(_ e : τ) #'(assign-type #'e #`τ)]
[(_ e τ) #'( e : τ)]))
;; assign-type Type -> Syntax