Compare commits
6 Commits
master
...
better-err
Author | SHA1 | Date | |
---|---|---|---|
![]() |
14960fd038 | ||
![]() |
cc502671a6 | ||
![]() |
83fb144c24 | ||
![]() |
76933bd3b1 | ||
![]() |
87bc0e44bc | ||
![]() |
b52ae2617b |
21
README.md
21
README.md
|
@ -45,10 +45,6 @@ Try it out: open up DrRacket and put the following in the definition area:
|
|||
(if true
|
||||
false
|
||||
true)
|
||||
|
||||
(: + (-> Nat Nat Nat))
|
||||
(define + plus)
|
||||
(+ z (s z))
|
||||
```
|
||||
|
||||
Try entering the following in the interaction area:
|
||||
|
@ -56,23 +52,6 @@ Try entering the following in the interaction area:
|
|||
(sub1 (s (s z)))
|
||||
```
|
||||
|
||||
Don't like parenthesis? Use Cur with sweet-expressions:
|
||||
```racket
|
||||
#lang sweet-exp cur
|
||||
require
|
||||
cur/stdlib/sugar
|
||||
cur/stdlib/bool
|
||||
cur/stdlib/nat
|
||||
|
||||
if true
|
||||
false
|
||||
true
|
||||
|
||||
define + plus
|
||||
|
||||
{z + s(z)}
|
||||
```
|
||||
|
||||
See the docs: `raco docs cur`.
|
||||
|
||||
Going further
|
||||
|
|
|
@ -17,7 +17,7 @@ Edwin C. Brady.
|
|||
@(define curnel-eval (curnel-sandbox "(require cur/stdlib/nat cur/stdlib/bool cur/stdlib/prop)"))
|
||||
|
||||
@defform*[((Type n)
|
||||
Type)]{
|
||||
Type)]{
|
||||
Define the universe of types at level @racket[n], where @racket[n] is any natural number.
|
||||
@racket[Type] is a synonym for @racket[(Type 0)]. Cur is impredicative
|
||||
in @racket[(Type 0)], although this is likely to change to a more
|
||||
|
@ -33,44 +33,43 @@ restricted impredicative universe.
|
|||
Type]
|
||||
}
|
||||
|
||||
@defform[(λ (id : type-expr) body-expr)]{
|
||||
Produces a single-arity procedure, binding the identifier @racket[id] of type
|
||||
@racket[type-expr] in @racket[body-expr] and in the type of @racket[body-expr].
|
||||
Both @racket[type-expr] and @racket[body-expr] can contain non-curnel forms,
|
||||
such as macros.
|
||||
@defform*[((lambda (id : type-expr) body-expr)
|
||||
(λ (id : type-expr) body-expr))]{
|
||||
Produces a single arity procedure, binding the identifier @racket[id] of type @racket[type-expr] in @racket[body-expr] and in the type of
|
||||
@racket[body-expr].
|
||||
Both @racket[type-expr] and @racket[body-expr] can contain non-curnel forms, such as macros.
|
||||
|
||||
Currently, Cur will return the underlying representation of a procedure when a
|
||||
@racket[λ] is evaluated at the top-level.
|
||||
Do not rely on this representation.
|
||||
Currently, Cur will return the underlying representation of a procedure when a @racket[lambda] is
|
||||
evaluated at the top-level. Do not rely on this representation.
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(λ (x : Type) x)]
|
||||
(lambda (x : Type) x)]
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(λ (x : Type) (λ (y : x) y))]
|
||||
(λ (x : Type) (lambda (y : x) y))]
|
||||
|
||||
|
||||
@defform[(#%app procedure argument)]{
|
||||
Applies the single-arity @racket[procedure] to @racket[argument].
|
||||
Applies the single arity @racket[procedure] to @racket[argument].
|
||||
}
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
((λ (x : (Type 1)) x) Type)]
|
||||
((lambda (x : (Type 1)) x) Type)]
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(#%app (λ (x : (Type 1)) x) Type)]
|
||||
(#%app (lambda (x : (Type 1)) x) Type)]
|
||||
}
|
||||
|
||||
@defform[(Π (id : type-expr) body-expr)]{
|
||||
Produces a dependent function type, binding the identifier @racket[id] of type
|
||||
@racket[type-expr] in @racket[body-expr].
|
||||
@defform*[((forall (id : type-expr) body-expr)
|
||||
(∀ (id : type-expr) body-expr))]{
|
||||
Produces a dependent function type, binding the identifier @racket[id] of type @racket[type-expr] in @racket[body-expr].
|
||||
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(Π (x : Type) Type)]
|
||||
(forall (x : Type) Type)]
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(λ (x : (Π (x : (Type 1)) Type))
|
||||
(lambda (x : (forall (x : (Type 1)) Type))
|
||||
(x Type))]
|
||||
}
|
||||
|
||||
|
@ -84,35 +83,32 @@ For instance, Cur does not currently perform strict positivity checking.
|
|||
(data Bool : Type
|
||||
(true : Bool)
|
||||
(false : Bool))
|
||||
((λ (x : Bool) x) true)
|
||||
((lambda (x : Bool) x) true)
|
||||
(data False : Type)
|
||||
(data And : (Π (A : Type) (Π (B : Type) Type))
|
||||
(conj : (Π (A : Type) (Π (B : Type) (Π (a : A) (Π (b : B) ((And A) B)))))))
|
||||
(data And : (forall (A : Type) (forall (B : Type) Type))
|
||||
(conj : (forall (A : Type) (forall (B : Type) (forall (a : A) (forall (b : B) ((And A) B)))))))
|
||||
((((conj Bool) Bool) true) false)]
|
||||
}
|
||||
|
||||
@defform[(elim inductive-type motive (index ...) (method ...) disc)]{
|
||||
Fold over the term @racket[disc] of the inductively defined type @racket[inductive-type].
|
||||
The @racket[motive] is a function that expects the indices of the inductive
|
||||
type and a term of the inductive type and produces the type that this
|
||||
fold returns.
|
||||
The type of @racket[disc] is @racket[(inductive-type index ...)].
|
||||
@racket[elim] takes one method for each constructor of @racket[inductive-type].
|
||||
Each @racket[method] expects the arguments for its corresponding constructor,
|
||||
and the inductive hypotheses generated by recursively eliminating all recursive
|
||||
arguments of the constructor.
|
||||
@defform[(elim type motive-universe)]{
|
||||
Returns the inductive eliminator for @racket[type] where the @racket[motive-universe] is the universe
|
||||
of the motive.
|
||||
The eliminator expects the next argument to be the motive, the next @racket[N] arguments to be the methods for
|
||||
each of the @racket[N] constructors of the inductive type @racket[type], the next @racket[P] arguments
|
||||
to be the parameters @racket[p_0 ... p_P] of the inductive @racket[type], and the final argument to be the term to
|
||||
eliminate of type @racket[(type p_0 ... p_P)].
|
||||
|
||||
The following example runs @racket[(sub1 (s z))].
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(data Nat : Type
|
||||
(z : Nat)
|
||||
(s : (Π (n : Nat) Nat)))
|
||||
(elim Nat (λ (x : Nat) Nat)
|
||||
()
|
||||
(z
|
||||
(λ (n : Nat) (λ (IH : Nat) n)))
|
||||
(s z))]
|
||||
(s : (forall (n : Nat) Nat)))
|
||||
(((((elim Nat Type)
|
||||
(lambda (x : Nat) Nat))
|
||||
z)
|
||||
(lambda (n : Nat) (lambda (IH : Nat) n)))
|
||||
(s z))]
|
||||
}
|
||||
|
||||
@defform[(define id expr)]{
|
||||
|
@ -121,13 +117,11 @@ Binds @racket[id] to the result of @racket[expr].
|
|||
@examples[#:eval curnel-eval
|
||||
(data Nat : Type
|
||||
(z : Nat)
|
||||
(s : (Π (n : Nat) Nat)))
|
||||
(define sub1 (λ (n : Nat)
|
||||
(elim Nat (λ (x : Nat) Nat)
|
||||
()
|
||||
(z
|
||||
(λ (n : Nat) (λ (IH : Nat) n)))
|
||||
n)))
|
||||
(s : (forall (n : Nat) Nat)))
|
||||
(define sub1 (lambda (n : Nat)
|
||||
(((((elim Nat Type) (lambda (x : Nat) Nat))
|
||||
z)
|
||||
(lambda (n : Nat) (lambda (IH : Nat) n))) n)))
|
||||
(sub1 (s (s z)))
|
||||
(sub1 (s z))
|
||||
(sub1 z)]
|
||||
|
|
|
@ -25,61 +25,61 @@ phase 1 in Cur.}
|
|||
|
||||
@examples[
|
||||
(eval:alts (define-syntax-rule (computed-type _) Type) (void))
|
||||
(eval:alts (cur-expand #'(λ (x : (computed-type bla)) x))
|
||||
(eval:result @racket[#'(λ (x : Type) x)] "" ""))
|
||||
(eval:alts (cur-expand #'(lambda (x : (computed-type bla)) x))
|
||||
(eval:result @racket[#'(lambda (x : Type) x)] "" ""))
|
||||
]
|
||||
}
|
||||
|
||||
@defproc[(cur-type-infer [syn syntax?])
|
||||
@defproc[(type-infer/syn [syn syntax?])
|
||||
(or/c syntax? #f)]{
|
||||
Returns the type of the Cur term @racket[syn], or @racket[#f] if no type could be inferred.
|
||||
|
||||
@examples[
|
||||
(eval:alts (cur-type-infer #'(λ (x : Type) x))
|
||||
(eval:result @racket[#'(Π (x : (Type 0)) (Type 0))] "" ""))
|
||||
(eval:alts (cur-type-infer #'Type)
|
||||
(eval:alts (type-infer/syn #'(lambda (x : Type) x))
|
||||
(eval:result @racket[#'(forall (x : (Type 0)) (Type 0))] "" ""))
|
||||
(eval:alts (type-infer/syn #'Type)
|
||||
(eval:result @racket[#'(Type 1)] "" ""))
|
||||
]
|
||||
}
|
||||
|
||||
@defproc[(cur-type-check? [syn syntax?])
|
||||
@defproc[(type-check/syn? [syn syntax?])
|
||||
boolean?]{
|
||||
Returns @racket[#t] if the Cur term @racket[syn] is well-typed, or @racket[#f] otherwise.
|
||||
|
||||
@examples[
|
||||
(eval:alts (cur-type-check? #'(λ (x : Type) x))
|
||||
(eval:alts (type-check/syn? #'(lambda (x : Type) x))
|
||||
(eval:result @racket[#t] "" ""))
|
||||
(eval:alts (cur-type-check? #'Type)
|
||||
(eval:alts (type-check/syn? #'Type)
|
||||
(eval:result @racket[#t] "" ""))
|
||||
(eval:alts (cur-type-check? #'x)
|
||||
(eval:alts (type-check/syn? #'x)
|
||||
(eval:result @racket[#f] "" ""))
|
||||
]
|
||||
}
|
||||
|
||||
@defproc[(cur-normalize [syn syntax?])
|
||||
@defproc[(normalize/syn [syn syntax?])
|
||||
syntax?]{
|
||||
Runs the Cur term @racket[syn] to a value.
|
||||
|
||||
@examples[
|
||||
(eval:alts (cur-normalize #'((λ (x : Type) x) Bool))
|
||||
(eval:alts (normalize/syn #'((lambda (x : Type) x) Bool))
|
||||
(eval:result @racket[#'Bool] "" ""))
|
||||
(eval:alts (cur-normalize #'(sub1 (s (s z))))
|
||||
(eval:alts (normalize/syn #'(sub1 (s (s z))))
|
||||
(eval:result @racket[#'(s z)] "" ""))
|
||||
]
|
||||
}
|
||||
|
||||
@defproc[(cur-step [syn syntax?])
|
||||
@defproc[(step/syn [syn syntax?])
|
||||
syntax?]{
|
||||
Runs the Cur term @racket[syn] for one step.
|
||||
|
||||
@examples[
|
||||
(eval:alts (cur-step #'((λ (x : Type) x) Bool))
|
||||
(eval:alts (step/syn #'((lambda (x : Type) x) Bool))
|
||||
(eval:result @racket[#'Bool] "" ""))
|
||||
(eval:alts (cur-step #'(sub1 (s (s z))))
|
||||
(eval:result @racket[#'(elim Nat (λ (x2 : Nat) Nat)
|
||||
()
|
||||
(z (λ (x2 : Nat) (λ (ih-n2 : Nat) x2)))
|
||||
(s (s z)))] "" ""))
|
||||
(eval:alts (step/syn #'(sub1 (s (s z))))
|
||||
(eval:result @racket[#'(((((elim Nat (Type 0))
|
||||
(lambda (x2 : Nat) Nat)) z)
|
||||
(lambda (x2 : Nat) (lambda (ih-n2 : Nat) x2)))
|
||||
(s (s z)))] "" ""))
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -90,11 +90,11 @@ equal modulo α and β-equivalence.
|
|||
@examples[
|
||||
|
||||
|
||||
(eval:alts (cur-equal? #'(λ (a : Type) a) #'(λ (b : Type) b))
|
||||
(eval:alts (cur-equal? #'(lambda (a : Type) a) #'(lambda (b : Type) b))
|
||||
(eval:result @racket[#t] "" ""))
|
||||
(eval:alts (cur-equal? #'((λ (a : Type) a) Bool) #'Bool)
|
||||
(eval:alts (cur-equal? #'((lambda (a : Type) a) Bool) #'Bool)
|
||||
(eval:result @racket[#t] "" ""))
|
||||
(eval:alts (cur-equal? #'(λ (a : Type) (sub1 (s z))) #'(λ (a : Type) z))
|
||||
(eval:alts (cur-equal? #'(lambda (a : Type) (sub1 (s z))) #'(lambda (a : Type) z))
|
||||
(eval:result @racket[#f] "" ""))
|
||||
]
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ Converts @racket[s] to a datum representation of the @tech{curnel form}, after e
|
|||
@examples[
|
||||
|
||||
|
||||
(eval:alts (cur->datum #'(λ (a : Type) a))
|
||||
(eval:alts (cur-?datum #'(lambda (a : Type) a))
|
||||
(eval:result @racket['(λ (a : (Unv 0) a))] "" ""))
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ Cur has a small standard library, primary for demonstration purposes.
|
|||
|
||||
@local-table-of-contents[]
|
||||
|
||||
@include-section{stdlib/tactics.scrbl}
|
||||
@include-section{stdlib/sugar.scrbl}
|
||||
@include-section{stdlib/bool.scrbl}
|
||||
@include-section{stdlib/nat.scrbl}
|
||||
@include-section{stdlib/maybe.scrbl}
|
||||
@include-section{stdlib/list.scrbl}
|
||||
@include-section{stdlib/typeclass.scrbl}
|
||||
@include-section{stdlib/tactics.scrbl}
|
||||
|
|
|
@ -22,7 +22,7 @@ A syntactic form that expands to the inductive eliminator for @racket[Bool]. Thi
|
|||
|
||||
@examples[#:eval curnel-eval
|
||||
(if true false true)
|
||||
(elim Bool (λ (x : Bool) Bool) () (false true) true)]
|
||||
(elim Bool Type (λ (x : Bool) Bool) false true true)]
|
||||
}
|
||||
|
||||
@defproc[(not [x Bool])
|
||||
|
|
|
@ -21,15 +21,12 @@ This library defines various syntactic extensions making Cur easier to write tha
|
|||
@defform*[((-> decl decl ... type)
|
||||
(→ decl decl ... type)
|
||||
(forall decl decl ... type)
|
||||
(∀ decl decl ... type)
|
||||
(Π decl decl ... type)
|
||||
(Pi decl decl ... type))
|
||||
(∀ decl decl ... type))
|
||||
#:grammar
|
||||
[(decl
|
||||
type
|
||||
(code:line (identifier : type)))]]{
|
||||
A multi-artiy function type that supports dependent and non-dependent type declarations and automatic currying.
|
||||
We provide lots of names for this form, because there are lots of synonyms in the literature.
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(data And : (-> Type Type Type)
|
||||
|
@ -62,24 +59,21 @@ Defines multi-arity procedure application via automatic currying.
|
|||
(conj Bool Bool true false)]
|
||||
}
|
||||
|
||||
@defform[(: name type)]{
|
||||
Declare that the @emph{function} which will be defined as @racket[name] has type @racket[type].
|
||||
Must precede the definition of @racket[name].
|
||||
@racket[type] must expand to a function type of the form @racket[(Π (x : t1) t2)]
|
||||
When used, this form allows omitting the annotations on arguments in the definition @racket[name]
|
||||
}
|
||||
|
||||
@defform*[((define name body)
|
||||
(define (name x ...) body)
|
||||
(define (name (x : t) ...) body))]{
|
||||
(define (name (x : t) ...) body))]{
|
||||
Like the @racket[define] provided by @racketmodname[cur], but supports
|
||||
defining curried functions via @racket[lambda].
|
||||
The second form, @racket[(define (name x ...) body)], can only be used when
|
||||
a @racket[(: name type)] form appears earlier in the module.
|
||||
}
|
||||
|
||||
@defform[(elim type motive-result-type e ...)]{
|
||||
Like the @racket[elim] provided by @racketmodname[cur], but supports
|
||||
automatically curries the remaining arguments @racket[e ...].
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
(: id (forall (A : Type) (a : A) A))
|
||||
(define (id A a) a)]
|
||||
(elim Bool Type (lambda (x : Bool) Bool)
|
||||
false
|
||||
true
|
||||
true)]
|
||||
}
|
||||
|
||||
@defform*[((define-type name type)
|
||||
|
@ -172,7 +166,7 @@ Check that expression @racket[e] has type @racket[type], causing a type-error if
|
|||
}
|
||||
|
||||
@defform[(run syn)]{
|
||||
Like @racket[cur-normalize], but is a syntactic form to be used in surface syntax.
|
||||
Like @racket[normalize/syn], but is a syntactic form to be used in surface syntax.
|
||||
Allows a Cur term to be written by computing part of the term from
|
||||
another Cur term.
|
||||
|
||||
|
@ -182,7 +176,7 @@ another Cur term.
|
|||
}
|
||||
|
||||
@defform[(step syn)]{
|
||||
Like @racket[run], but uses @racket[cur-step] to evaluate only one step and prints intermediate
|
||||
Like @racket[run], but uses @racket[step/syn] to evaluate only one step and prints intermediate
|
||||
results before returning the result of evaluation.
|
||||
|
||||
@examples[#:eval curnel-eval
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#lang info
|
||||
(define collection 'multi)
|
||||
(define deps '("base" "racket-doc"))
|
||||
(define build-deps '("scribble-lib" ("cur-lib" #:version "0.4") "sandbox-lib"))
|
||||
(define build-deps '("scribble-lib" ("cur-lib" #:version "0.2") "sandbox-lib"))
|
||||
(define pkg-desc "Documentation for \"cur\".")
|
||||
(define pkg-authors '(wilbowma))
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
(define-language ttL
|
||||
(i j k ::= natural)
|
||||
(U ::= (Unv i))
|
||||
(D x c ::= variable-not-otherwise-mentioned)
|
||||
(t e ::= U (λ (x : t) e) x (Π (x : t) t) (e e) (elim D U))
|
||||
;; Δ (signature). (inductive-name : type ((constructor : type) ...))
|
||||
;; NB: Δ is a map from a name x to a pair of it's type and a map of constructor names to their types
|
||||
(Δ ::= ∅ (Δ (D : t ((c : t) ...))))
|
||||
(t e ::= U (λ (x : t) e) x (Π (x : t) t) (e e)
|
||||
;; (elim inductive-type motive (indices ...) (methods ...) discriminant)
|
||||
(elim D e (e ...) (e ...) e))
|
||||
(D x c ::= variable-not-otherwise-mentioned)
|
||||
#:binding-forms
|
||||
(λ (x : t) e #:refers-to x)
|
||||
(Π (x : t_0) t_1 #:refers-to x))
|
||||
|
@ -44,8 +44,6 @@
|
|||
;;; ------------------------------------------------------------------------
|
||||
;;; Universe typing
|
||||
|
||||
;; Universe types
|
||||
;; aka Axioms A of a PTS
|
||||
(define-judgment-form ttL
|
||||
#:mode (unv-type I O)
|
||||
#:contract (unv-type U U)
|
||||
|
@ -55,7 +53,6 @@
|
|||
(unv-type (Unv i_0) (Unv i_1))])
|
||||
|
||||
;; Universe predicativity rules. Impredicative in (Unv 0)
|
||||
;; aka Rules R of a PTS
|
||||
(define-judgment-form ttL
|
||||
#:mode (unv-pred I I O)
|
||||
#:contract (unv-pred U U U)
|
||||
|
@ -108,6 +105,27 @@
|
|||
[(Δ-union Δ_2 (Δ_1 (x : t any)))
|
||||
((Δ-union Δ_2 Δ_1) (x : t any))])
|
||||
|
||||
;; Returns the inductively defined type that x constructs
|
||||
;; NB: Depends on clause order
|
||||
(define-metafunction ttL
|
||||
Δ-key-by-constructor : Δ x -> x or #f
|
||||
[(Δ-key-by-constructor (Δ (x : t ((x_0 : t_0) ... (x_c : t_c) (x_1 : t_1) ...))) x_c)
|
||||
x]
|
||||
[(Δ-key-by-constructor (Δ (x_1 : t_1 any)) x)
|
||||
(Δ-key-by-constructor Δ x)]
|
||||
[(Δ-key-by-constructor Δ x)
|
||||
#f])
|
||||
|
||||
;; Returns the constructor map for the inductively defined type x_D in the signature Δ
|
||||
(define-metafunction ttL
|
||||
Δ-ref-constructor-map : Δ x -> ((x : t) ...) or #f
|
||||
;; NB: Depends on clause order
|
||||
[(Δ-ref-constructor-map ∅ x_D) #f]
|
||||
[(Δ-ref-constructor-map (Δ (x_D : t_D any)) x_D)
|
||||
any]
|
||||
[(Δ-ref-constructor-map (Δ (x_1 : t_1 any)) x_D)
|
||||
(Δ-ref-constructor-map Δ x_D)])
|
||||
|
||||
;; TODO: Should not use Δ-ref-type
|
||||
(define-metafunction ttL
|
||||
Δ-ref-constructor-type : Δ x x -> t
|
||||
|
@ -127,6 +145,14 @@
|
|||
;; TODO: Mix of pure Redex/escaping to Racket sometimes is getting confusing.
|
||||
;; TODO: Justify, or stop.
|
||||
|
||||
;; Return the number of constructors that D has
|
||||
(define-metafunction ttL
|
||||
Δ-constructor-count : Δ D -> natural or #f
|
||||
[(Δ-constructor-count Δ D)
|
||||
,(length (term (x ...)))
|
||||
(where (x ...) (Δ-ref-constructors Δ D))]
|
||||
[(Δ-constructor-count Δ D) #f])
|
||||
|
||||
;; NB: Depends on clause order
|
||||
(define-metafunction ttL
|
||||
sequence-index-of : any (any ...) -> natural
|
||||
|
@ -163,31 +189,47 @@
|
|||
;; TODO: Test
|
||||
#| TODO:
|
||||
| This essentially eta-expands t at the type-level. Why is this necessary? Shouldn't it be true
|
||||
| that (convert t (Ξ-apply Ξ t))?
|
||||
| Maybe not. t is a lambda whose type is convert to (Ξ-apply Ξ t)? Yes.
|
||||
| that (equivalent t (Ξ-apply Ξ t))?
|
||||
| Maybe not. t is a lambda whose type is equivalent to (Ξ-apply Ξ t)? Yes.
|
||||
|#
|
||||
(define-metafunction tt-ctxtL
|
||||
Ξ-apply : Ξ t -> t
|
||||
[(Ξ-apply hole t) t]
|
||||
[(Ξ-apply (Π (x : t) Ξ) t_0) (Ξ-apply Ξ (t_0 x))])
|
||||
|
||||
;; Compose multiple telescopes into a single telescope:
|
||||
(define-metafunction tt-ctxtL
|
||||
Ξ-compose : Ξ Ξ ... -> Ξ
|
||||
[(Ξ-compose Ξ) Ξ]
|
||||
[(Ξ-compose Ξ_0 Ξ_1 Ξ_rest ...)
|
||||
(Ξ-compose (in-hole Ξ_0 Ξ_1) Ξ_rest ...)])
|
||||
|
||||
;; Compute the number of arguments in a Ξ
|
||||
(define-metafunction tt-ctxtL
|
||||
Ξ-length : Ξ -> natural
|
||||
[(Ξ-length hole) 0]
|
||||
[(Ξ-length (Π (x : t) Ξ)) ,(add1 (term (Ξ-length Ξ)))])
|
||||
|
||||
;; Compute the number of applications in a Θ
|
||||
(define-metafunction tt-ctxtL
|
||||
Θ-length : Θ -> natural
|
||||
[(Θ-length hole) 0]
|
||||
[(Θ-length (Θ e)) ,(add1 (term (Θ-length Θ)))])
|
||||
|
||||
;; Convert an apply context to a sequence of terms
|
||||
(define-metafunction tt-ctxtL
|
||||
Θ->list : Θ -> (e ...)
|
||||
[(Θ->list hole) ()]
|
||||
[(Θ->list (Θ e))
|
||||
(e_r ... e)
|
||||
(where (e_r ...) (Θ->list Θ))])
|
||||
|
||||
(define-metafunction tt-ctxtL
|
||||
list->Θ : (e ...) -> Θ
|
||||
[(list->Θ ()) hole]
|
||||
[(list->Θ (e e_r ...))
|
||||
(in-hole (list->Θ (e_r ...)) (hole e))])
|
||||
|
||||
(define-metafunction tt-ctxtL
|
||||
apply : e e ... -> e
|
||||
[(apply e_f e ...)
|
||||
(in-hole (list->Θ (e ...)) e_f)])
|
||||
|
||||
;; Reference an expression in Θ by index; index 0 corresponds to the the expression applied to a hole.
|
||||
(define-metafunction tt-ctxtL
|
||||
Θ-ref : Θ natural -> e or #f
|
||||
|
@ -209,6 +251,15 @@
|
|||
[(Δ-ref-parameter-Ξ Δ x)
|
||||
#f])
|
||||
|
||||
;; Return the number of parameters of D
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-parameter-count : Δ D -> natural or #f
|
||||
[(Δ-parameter-count Δ D)
|
||||
(Ξ-length Ξ)
|
||||
(where Ξ (Δ-ref-parameter-Ξ Δ D))]
|
||||
[(Δ-parameter-count Δ D)
|
||||
#f])
|
||||
|
||||
;; Returns the telescope of the arguments for the constructor x_ci of the inductively defined type x_D
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-constructor-telescope : Δ x x -> Ξ
|
||||
|
@ -226,6 +277,21 @@
|
|||
(where (in-hole Ξ (in-hole Θ x_D))
|
||||
(Δ-ref-constructor-type Δ x_D x_ci))])
|
||||
|
||||
;; Inner loop for Δ-constructor-noninductive-telescope
|
||||
(define-metafunction tt-ctxtL
|
||||
noninductive-loop : x Φ -> Φ
|
||||
[(noninductive-loop x_D hole) hole]
|
||||
[(noninductive-loop x_D (Π (x : (in-hole Φ (in-hole Θ x_D))) Φ_1))
|
||||
(noninductive-loop x_D Φ_1)]
|
||||
[(noninductive-loop x_D (Π (x : t) Φ_1))
|
||||
(Π (x : t) (noninductive-loop x_D Φ_1))])
|
||||
|
||||
;; Returns the noninductive arguments to the constructor x_ci of the inductively defined type x_D
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-constructor-noninductive-telescope : Δ x x -> Ξ
|
||||
[(Δ-constructor-noninductive-telescope Δ x_D x_ci)
|
||||
(noninductive-loop x_D (Δ-constructor-telescope Δ x_D x_ci))])
|
||||
|
||||
;; Inner loop for Δ-constructor-inductive-telescope
|
||||
;; NB: Depends on clause order
|
||||
(define-metafunction tt-ctxtL
|
||||
|
@ -254,6 +320,36 @@
|
|||
(hypotheses-loop x_D t_P Φ_1))
|
||||
(where x_h ,(variable-not-in (term (x_D t_P any_0)) 'x-ih))])
|
||||
|
||||
;; Returns the inductive hypotheses required for the elimination method of constructor x_ci for
|
||||
;; inductive type x_D, when eliminating with motive t_P.
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-constructor-inductive-hypotheses : Δ x x t -> Ξ
|
||||
[(Δ-constructor-inductive-hypotheses Δ x_D x_ci t_P)
|
||||
(hypotheses-loop x_D t_P (Δ-constructor-inductive-telescope Δ x_D x_ci))])
|
||||
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-constructor-method-telescope : Δ x x t -> Ξ
|
||||
[(Δ-constructor-method-telescope Δ x_D x_ci t_P)
|
||||
(Π (x_mi : (in-hole Ξ_a (in-hole Ξ_h ((in-hole Θ_p t_P) (Ξ-apply Ξ_a x_ci)))))
|
||||
hole)
|
||||
(where Θ_p (Δ-constructor-parameters Δ x_D x_ci))
|
||||
(where Ξ_a (Δ-constructor-telescope Δ x_D x_ci))
|
||||
(where Ξ_h (Δ-constructor-inductive-hypotheses Δ x_D x_ci t_P))
|
||||
(where x_mi ,(variable-not-in (term (t_P Δ)) 'x-mi))])
|
||||
|
||||
;; fold Ξ-compose over map Δ-constructor-method-telescope over the list of constructors
|
||||
(define-metafunction tt-ctxtL
|
||||
method-loop : Δ x t (x ...) -> Ξ
|
||||
[(method-loop Δ x_D t_P ()) hole]
|
||||
[(method-loop Δ x_D t_P (x_0 x_rest ...))
|
||||
(Ξ-compose (Δ-constructor-method-telescope Δ x_D x_0 t_P) (method-loop Δ x_D t_P (x_rest ...)))])
|
||||
|
||||
;; Returns the telescope of all methods required to eliminate the type x_D with motive t_P
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-methods-telescope : Δ x t -> Ξ
|
||||
[(Δ-methods-telescope Δ x_D t_P)
|
||||
(method-loop Δ x_D t_P (Δ-ref-constructors Δ x_D))])
|
||||
|
||||
;; Computes the type of the eliminator for the inductively defined type x_D with a motive whose result
|
||||
;; is in universe U.
|
||||
;;
|
||||
|
@ -269,40 +365,29 @@
|
|||
;; Ξ_P*D is the telescope of the parameters of x_D and
|
||||
;; the witness of type x_D (applied to the parameters)
|
||||
;; Ξ_m is the telescope of the methods for x_D
|
||||
|
||||
;; Returns the inductive hypotheses required for the elimination method of constructor c_i for
|
||||
;; inductive type D, when eliminating with motive t_P.
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-constructor-inductive-hypotheses : Δ D c t -> Ξ
|
||||
[(Δ-constructor-inductive-hypotheses Δ D c_i t_P)
|
||||
(hypotheses-loop D t_P (Δ-constructor-inductive-telescope Δ D c_i))])
|
||||
|
||||
;; Returns the type of the method corresponding to c_i
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-constructor-method-type : Δ D c t -> t
|
||||
[(Δ-constructor-method-type Δ D c_i t_P)
|
||||
(in-hole Ξ_a (in-hole Ξ_h ((in-hole Θ_p t_P) (Ξ-apply Ξ_a c_i))))
|
||||
(where Θ_p (Δ-constructor-parameters Δ D c_i))
|
||||
(where Ξ_a (Δ-constructor-telescope Δ D c_i))
|
||||
(where Ξ_h (Δ-constructor-inductive-hypotheses Δ D c_i t_P))])
|
||||
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-method-types : Δ D e -> (t ...)
|
||||
[(Δ-method-types Δ D e)
|
||||
,(map (lambda (c) (term (Δ-constructor-method-type Δ D ,c e))) (term (c ...)))
|
||||
(where (c ...) (Δ-ref-constructors Δ D))])
|
||||
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-motive-type : Δ D U -> t
|
||||
[(Δ-motive-type Δ D U)
|
||||
(in-hole Ξ_P*D U)
|
||||
(where Ξ (Δ-ref-parameter-Ξ Δ D))
|
||||
Δ-elim-type : Δ x U -> t
|
||||
[(Δ-elim-type Δ x_D U)
|
||||
(Π (x_P : (in-hole Ξ_P*D U))
|
||||
;; The methods Ξ_m for each constructor of type x_D
|
||||
(in-hole Ξ_m
|
||||
;; And finally, the parameters and discriminant
|
||||
(in-hole Ξ_P*D
|
||||
;; The result is (P a ... (x_D a ...)), i.e., the motive
|
||||
;; applied to the paramters and discriminant
|
||||
(Ξ-apply Ξ_P*D x_P))))
|
||||
;; Get the parameters of x_D
|
||||
(where Ξ (Δ-ref-parameter-Ξ Δ x_D))
|
||||
;; A fresh name to bind the discriminant
|
||||
(where x ,(variable-not-in (term (Δ D Ξ)) 'x-D))
|
||||
(where x ,(variable-not-in (term (Δ Γ x_D Ξ)) 'x-D))
|
||||
;; The telescope (∀ a -> ... -> (D a ...) hole), i.e.,
|
||||
;; of the indices and the inductive type applied to the
|
||||
;; indices
|
||||
(where Ξ_P*D (in-hole Ξ (Π (x : (Ξ-apply Ξ D)) hole)))])
|
||||
;; of the parameters and the inductive type applied to the
|
||||
;; parameters
|
||||
(where Ξ_P*D (in-hole Ξ (Π (x : (Ξ-apply Ξ x_D)) hole)))
|
||||
;; A fresh name for the motive
|
||||
(where x_P ,(variable-not-in (term (Δ Γ x_D Ξ Ξ_P*D x)) 'x-P))
|
||||
;; The types of the methods for this inductive.
|
||||
(where Ξ_m (Δ-methods-telescope Δ x_D x_P))])
|
||||
|
||||
;;; ------------------------------------------------------------------------
|
||||
;;; Dynamic semantics
|
||||
|
@ -310,21 +395,16 @@
|
|||
;;; inductively defined type x with a motive whose result is in universe U
|
||||
|
||||
(define-extended-language tt-redL tt-ctxtL
|
||||
(v ::= x U (Π (x : t) t) (λ (x : t) t) (in-hole Θv c))
|
||||
(Θv ::= hole (Θv v))
|
||||
(C-elim ::= (elim D t_P (e_i ...) (e_m ...) hole))
|
||||
;; call-by-value
|
||||
(E ::= hole (E e) (v E)
|
||||
(elim D e (e ...) (v ... E e ...) e)
|
||||
(elim D e (e ...) (v ...) E)
|
||||
;; reduce under Π (helps with typing checking)
|
||||
;; TODO: Should be done in conversion judgment
|
||||
(Π (x : v) E) (Π (x : E) e)))
|
||||
;; NB: (in-hole Θv (elim x U)) is only a value when it's a partially applied elim. However,
|
||||
;; determining whether or not it is partially applied cannot be done with the grammar alone.
|
||||
(v ::= x U (Π (x : t) t) (λ (x : t) t) (elim x U) (in-hole Θv x) (in-hole Θv (elim x U)))
|
||||
(Θv ::= hole (Θv v))
|
||||
;; call-by-value, plus reduce under Π (helps with typing checking)
|
||||
(E ::= hole (E e) (v E) (Π (x : v) E) (Π (x : E) e)))
|
||||
|
||||
(define Θv? (redex-match? tt-redL Θv))
|
||||
(define E? (redex-match? tt-redL E))
|
||||
(define v? (redex-match? tt-redL v))
|
||||
|
||||
#|
|
||||
| The elim form must appear applied like so:
|
||||
| (elim D U v_P m_0 ... m_i m_j ... m_n p ... (c_i a ...))
|
||||
|
@ -340,6 +420,75 @@
|
|||
|
|
||||
| Using contexts, this appears as (in-hole Θ ((elim D U) v_P))
|
||||
|#
|
||||
|
||||
|
||||
;;; NB: Next 3 meta-function Assume of Θ n constructors, j parameters, n+j+1-th element is discriminant
|
||||
|
||||
;; Given the apply context Θ in which an elimination of D with motive
|
||||
;; v of type U appears, extract the parameters p ... from Θ.
|
||||
(define-metafunction tt-redL
|
||||
elim-parameters : Δ D Θ -> Θ
|
||||
[(elim-parameters Δ D Θ)
|
||||
;; Drop the methods, take the parameters
|
||||
(list->Θ
|
||||
,(take
|
||||
(drop (term (Θ->list Θ)) (term (Δ-constructor-count Δ D)))
|
||||
(term (Δ-parameter-count Δ D))))])
|
||||
|
||||
;; Given the apply context Θ in which an elimination of D with motive
|
||||
;; v of type U appears, extract the methods m_0 ... m_n from Θ.
|
||||
(define-metafunction tt-redL
|
||||
elim-methods : Δ D Θ -> Θ
|
||||
[(elim-methods Δ D Θ)
|
||||
;; Take the methods, one for each constructor
|
||||
(list->Θ
|
||||
,(take
|
||||
(term (Θ->list Θ))
|
||||
(term (Δ-constructor-count Δ D))))])
|
||||
|
||||
;; Given the apply context Θ in which an elimination of D with motive
|
||||
;; v of type U appears, extract the discriminant (c_i a ...) from Θ.
|
||||
(define-metafunction tt-redL
|
||||
elim-discriminant : Δ D Θ -> e
|
||||
[(elim-discriminant Δ D Θ)
|
||||
;; Drop the methods, the parameters, and take the last element
|
||||
,(car
|
||||
(drop
|
||||
(drop (term (Θ->list Θ)) (term (Δ-constructor-count Δ D)))
|
||||
(term (Δ-parameter-count Δ D))))])
|
||||
|
||||
;; Check that Θ is valid and ready to be evaluated as the arguments to an elim.
|
||||
;; has length m = n + j + 1 and D has n constructors and j parameters,
|
||||
;; and the 1 represents the discriminant.
|
||||
;; discharges assumption for previous 3 meta-functions
|
||||
(define-metafunction tt-redL
|
||||
Θ-valid : Δ D Θ -> #t or #f
|
||||
[(Θ-valid Δ D Θ)
|
||||
#t
|
||||
(where natural_m (Θ-length Θ))
|
||||
(where natural_n (Δ-constructor-count Δ D))
|
||||
(where natural_j (Δ-parameter-count Δ D))
|
||||
(side-condition (= (+ (term natural_n) (term natural_j) 1) (term natural_m)))
|
||||
;; As Cur allows reducing (through reflection) open terms,
|
||||
;; check that the discriminant is a canonical form so that
|
||||
;; reduction can proceed; otherwise not valid.
|
||||
(where (in-hole Θ_i c_i) (elim-discriminant Δ D Θ))
|
||||
(where D (Δ-key-by-constructor Δ c_i))]
|
||||
[(Θ-valid Δ D Θ) #f])
|
||||
|
||||
(module+ test
|
||||
(require rackunit)
|
||||
(check-equal?
|
||||
(term (Θ-length (((hole (s zero)) (λ (x : nat) (λ (ih-x : nat) (s (s x))))) zero)))
|
||||
3)
|
||||
(check-true
|
||||
(term
|
||||
(Θ-valid
|
||||
((∅ (nat : (Unv 0) ((zero : nat) (s : (Π (x : nat) nat))))) (bool : (Unv 0) ((true : bool) (false : bool))))
|
||||
nat
|
||||
(((hole (s zero)) (λ (x : nat) (λ (ih-x : nat) (s (s x))))) zero)))))
|
||||
|
||||
|
||||
(define-metafunction tt-ctxtL
|
||||
is-inductive-argument : Δ D t -> #t or #f
|
||||
;; Think this only works in call-by-value. A better solution would
|
||||
|
@ -353,34 +502,39 @@
|
|||
;; x_ci for x_D, for each inductively smaller term t_i of type (in-hole Θ_p x_D) inside Θ_i,
|
||||
;; generate: (elim x_D U t_P Θ_m ... Θ_p ... t_i)
|
||||
;; TODO TTEESSSSSTTTTTTTT
|
||||
(define-metafunction tt-redL
|
||||
Δ-inductive-elim : Δ D C-elim Θ -> Θ
|
||||
(define-metafunction tt-ctxtL
|
||||
Δ-inductive-elim : Δ x U t Θ Θ Θ -> Θ
|
||||
;; NB: If metafunction fails, recursive
|
||||
;; NB: elimination will be wrong. This will introduced extremely sublte bugs,
|
||||
;; NB: inconsistency, failure of type safety, and other bad things.
|
||||
;; NB: It should be tested and audited thoroughly
|
||||
[(Δ-inductive-elim any ... hole)
|
||||
hole]
|
||||
[(Δ-inductive-elim Δ D C-elim (Θ_c t_i))
|
||||
((Δ-inductive-elim Δ D C-elim Θ_c)
|
||||
(in-hole C-elim t_i))
|
||||
(side-condition (term (is-inductive-argument Δ D t_i)))]
|
||||
[(Δ-inductive-elim any ... (Θ_c t_i))
|
||||
(Δ-inductive-elim any ... Θ_c)])
|
||||
[(Δ-inductive-elim Δ x_D U t_P Θ_p Θ_m (Θ_i t_i))
|
||||
((Δ-inductive-elim Δ x_D U t_P Θ_p Θ_m Θ_i)
|
||||
(in-hole ((in-hole Θ_p Θ_m) t_i) ((elim x_D U) t_P)))
|
||||
(side-condition (term (is-inductive-argument Δ x_D t_i)))]
|
||||
[(Δ-inductive-elim Δ x_D U t_P Θ_p Θ_m (Θ_i t_i))
|
||||
(Δ-inductive-elim Δ x_D U t_P Θ_p Θ_m Θ_i)]
|
||||
[(Δ-inductive-elim Δ x_D U t_P Θ_p Θ_m hole)
|
||||
hole])
|
||||
|
||||
(define tt-->
|
||||
(reduction-relation tt-redL
|
||||
(--> (Δ (in-hole E ((λ (x : t_0) t_1) t_2)))
|
||||
(Δ (in-hole E (subst t_1 x t_2)))
|
||||
-->β)
|
||||
(--> (Δ (in-hole E (elim D e_motive (e_i ...) (v_m ...) (in-hole Θv_c c))))
|
||||
(Δ (in-hole E (in-hole Θ_mi v_mi)))
|
||||
;; Find the method for constructor c_i, relying on the order of the arguments.
|
||||
(where natural (Δ-constructor-index Δ D c))
|
||||
(where v_mi ,(list-ref (term (v_m ...)) (term natural)))
|
||||
(--> (Δ (in-hole E (in-hole Θv ((elim D U) v_P))))
|
||||
(Δ (in-hole E (in-hole Θ_r (in-hole Θv_i v_mi))))
|
||||
;; Check that Θv is valid to avoid capturing other things
|
||||
(side-condition (term (Θ-valid Δ D Θv)))
|
||||
;; Split Θv into its components: the paramters Θv_P for x_D, the methods Θv_m for x_D, and
|
||||
;; the discriminant: the constructor c_i applied to its argument Θv_i
|
||||
(where Θv_p (elim-parameters Δ D Θv))
|
||||
(where Θv_m (elim-methods Δ D Θv))
|
||||
(where (in-hole Θv_i c_i) (elim-discriminant Δ D Θv))
|
||||
;; Find the method for constructor x_ci, relying on the order of the arguments.
|
||||
(where v_mi (Θ-ref Θv_m (Δ-constructor-index Δ D c_i)))
|
||||
;; Generate the inductive recursion
|
||||
(where Θ_ih (Δ-inductive-elim Δ D (elim D e_motive (e_i ...) (v_m ...) hole) Θv_c))
|
||||
(where Θ_mi (in-hole Θ_ih Θv_c))
|
||||
(where Θ_r (Δ-inductive-elim Δ D U v_P Θv_p Θv_m Θv_i))
|
||||
-->elim)))
|
||||
|
||||
(define-metafunction tt-redL
|
||||
|
@ -396,6 +550,16 @@
|
|||
(where (_ e_r)
|
||||
,(car (apply-reduction-relation* tt--> (term (Δ e)) #:cache-all? #t)))])
|
||||
|
||||
(define-judgment-form tt-redL
|
||||
#:mode (equivalent I I I)
|
||||
#:contract (equivalent Δ t t)
|
||||
|
||||
[(where t_2 (reduce Δ t_0))
|
||||
(where t_3 (reduce Δ t_1))
|
||||
(side-condition (α-equivalent? t_2 t_3))
|
||||
----------------- "≡-αβ"
|
||||
(equivalent Δ t_0 t_1)])
|
||||
|
||||
;;; ------------------------------------------------------------------------
|
||||
;;; Type checking and synthesis
|
||||
|
||||
|
@ -405,24 +569,6 @@
|
|||
(Γ ::= ∅ (Γ x : t)))
|
||||
(define Γ? (redex-match? tt-typingL Γ))
|
||||
|
||||
(define-judgment-form tt-typingL
|
||||
#:mode (convert I I I I)
|
||||
#:contract (convert Δ Γ t t)
|
||||
|
||||
[(side-condition ,(<= (term i_0) (term i_1)))
|
||||
----------------- "≼-Unv"
|
||||
(convert Δ Γ (Unv i_0) (Unv i_1))]
|
||||
|
||||
[(where t_2 (reduce Δ t_0))
|
||||
(where t_3 (reduce Δ t_1))
|
||||
(side-condition (α-equivalent? t_2 t_3))
|
||||
----------------- "≼-αβ"
|
||||
(convert Δ Γ t_0 t_1)]
|
||||
|
||||
[(convert Δ (Γ x : t_0) t_1 t_2)
|
||||
----------------- "≼-Π"
|
||||
(convert Δ Γ (Π (x : t_0) t_1) (Π (x : t_0) t_2))])
|
||||
|
||||
(define-metafunction tt-typingL
|
||||
Γ-union : Γ Γ -> Γ
|
||||
[(Γ-union Γ ∅) Γ]
|
||||
|
@ -541,22 +687,16 @@
|
|||
----------------- "DTR-Application"
|
||||
(type-infer Δ Γ (e_0 e_1) t_3)]
|
||||
|
||||
[(type-check Δ Γ e_c (apply D e_i ...))
|
||||
|
||||
(type-infer Δ Γ e_motive (name t_motive (in-hole Ξ U)))
|
||||
(convert Δ Γ t_motive (Δ-motive-type Δ D U))
|
||||
|
||||
(where (t_m ...) (Δ-method-types Δ D e_motive))
|
||||
(type-check Δ Γ e_m t_m) ...
|
||||
[(where t (Δ-elim-type Δ D U))
|
||||
(type-infer Δ Γ t U_e)
|
||||
----------------- "DTR-Elim_D"
|
||||
(type-infer Δ Γ (elim D e_motive (e_i ...) (e_m ...) e_c)
|
||||
(apply e_motive e_i ... e_c))])
|
||||
(type-infer Δ Γ (elim D U) t)])
|
||||
|
||||
(define-judgment-form tt-typingL
|
||||
#:mode (type-check I I I I)
|
||||
#:contract (type-check Δ Γ e t)
|
||||
|
||||
[(type-infer Δ Γ e t_0)
|
||||
(convert Δ Γ t t_0)
|
||||
(equivalent Δ t t_0)
|
||||
----------------- "DTR-Check"
|
||||
(type-check Δ Γ e t)])
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
;; This module just provide module language sugar over the redex model.
|
||||
|
||||
(require
|
||||
(except-in "redex-core.rkt" apply)
|
||||
"redex-core.rkt"
|
||||
redex/reduction-semantics
|
||||
racket/provide-syntax
|
||||
(for-syntax
|
||||
|
@ -11,7 +11,7 @@
|
|||
racket/syntax
|
||||
(except-in racket/provide-transform export)
|
||||
racket/require-transform
|
||||
(except-in "redex-core.rkt" apply)
|
||||
"redex-core.rkt"
|
||||
redex/reduction-semantics))
|
||||
(provide
|
||||
;; Basic syntax
|
||||
|
@ -30,10 +30,10 @@
|
|||
[dep-provide provide]
|
||||
[dep-require require]
|
||||
|
||||
[dep-lambda λ]
|
||||
[dep-lambda lambda]
|
||||
[dep-app #%app]
|
||||
|
||||
[dep-forall Π]
|
||||
[dep-forall forall]
|
||||
|
||||
[dep-inductive data]
|
||||
|
||||
|
@ -58,13 +58,41 @@
|
|||
(all-from-out syntax/parse)
|
||||
(all-from-out racket)
|
||||
(all-from-out racket/syntax)
|
||||
cur->datum
|
||||
cur-expand
|
||||
cur-type-infer
|
||||
cur-type-check?
|
||||
cur-normalize
|
||||
cur-step
|
||||
cur-equal?))
|
||||
raise-curnel-type-error
|
||||
raise-curnel-syntax-error
|
||||
cur->datum
|
||||
cur-expand
|
||||
type-infer/syn
|
||||
type-check/syn?
|
||||
normalize/syn
|
||||
step/syn
|
||||
cur-equal?))
|
||||
|
||||
;; Exceptions
|
||||
(begin-for-syntax
|
||||
(provide
|
||||
(struct-out exn:cur)
|
||||
(struct-out exn:cur:curnel)
|
||||
(struct-out exn:cur:curnel:type)
|
||||
(struct-out exn:cur:curnel:syntax))
|
||||
(define-struct (exn:cur exn) () #:transparent)
|
||||
(define-struct (exn:cur:curnel exn:cur) () #:transparent)
|
||||
(define-struct (exn:cur:curnel:type exn:cur) () #:transparent)
|
||||
(define-struct (exn:cur:curnel:syntax exn:cur) () #:transparent)
|
||||
|
||||
(define (raise-curnel-type-error name v . other)
|
||||
(raise
|
||||
(make-exn:cur:curnel:type
|
||||
(for/fold ([msg (format "~a: Cur type error;~n Typing judgment did not hold in Curnel~n term: ~a" name v)])
|
||||
([t other])
|
||||
(format "~a~n additional context: ~a" msg t))
|
||||
(current-continuation-marks))))
|
||||
|
||||
(define (raise-curnel-syntax-error name v [more ""])
|
||||
(raise
|
||||
(make-exn:cur:curnel:syntax
|
||||
(format "~a: Cur syntax error;~n Term is invalid Curnel syntax;~a~n term: ~a" name more v)
|
||||
(current-continuation-marks)))))
|
||||
|
||||
(begin-for-syntax
|
||||
;; TODO: Gamma and Delta seem to get reset inside a module+
|
||||
|
@ -73,7 +101,7 @@
|
|||
(term ∅)
|
||||
(lambda (x)
|
||||
(unless (Γ? x)
|
||||
(error 'core-error "We built a bad term environment ~s" x))
|
||||
(raise-curnel-syntax-error 'term-environment "term is not a well-formed Γ"))
|
||||
x)))
|
||||
|
||||
(define delta
|
||||
|
@ -81,7 +109,7 @@
|
|||
(term ∅)
|
||||
(lambda (x)
|
||||
(unless (Δ? x)
|
||||
(error 'core-error "We built a bad inductive declaration ~s" x))
|
||||
(raise-curnel-syntax-error 'inductive-delcaration x "term is not a well-formed Δ"))
|
||||
x)))
|
||||
|
||||
;; These should be provided by core, so details of envs can be hidden.
|
||||
|
@ -118,7 +146,7 @@
|
|||
(list null null)
|
||||
(lambda (x)
|
||||
(unless (subst? x)
|
||||
(error 'core-error "We build a bad subst ~s" x))
|
||||
(raise-curnel-syntax-error 'top-level-bindings x))
|
||||
x)))
|
||||
|
||||
(define (add-binding/term! x t)
|
||||
|
@ -156,8 +184,6 @@
|
|||
(define (cur->datum syn)
|
||||
;; Main loop; avoid type
|
||||
(define reified-term
|
||||
;; TODO: This results in less good error messages. Add an
|
||||
;; algorithm to find the smallest ill-typed term.
|
||||
(parameterize ([inner-expand? #t])
|
||||
(let cur->datum ([syn syn])
|
||||
(syntax-parse (core-expand syn)
|
||||
|
@ -177,16 +203,15 @@
|
|||
[e (parameterize ([gamma (extend-Γ/term gamma x t)])
|
||||
(cur->datum #'e))])
|
||||
(term (,(syntax->datum #'b) (,x : ,t) ,e)))]
|
||||
[(elim D motive (i ...) (m ...) d)
|
||||
(term (elim ,(cur->datum #'D) ,(cur->datum #'motive)
|
||||
,(map cur->datum (syntax->list #'(i ...)))
|
||||
,(map cur->datum (syntax->list #'(m ...)))
|
||||
,(cur->datum #'d)))]
|
||||
[(elim t1 t2)
|
||||
(let* ([t1 (cur->datum #'t1)]
|
||||
[t2 (cur->datum #'t2)])
|
||||
(term (elim ,t1 ,t2)))]
|
||||
[(#%app e1 e2)
|
||||
(term (,(cur->datum #'e1) ,(cur->datum #'e2)))]))))
|
||||
(unless (or (inner-expand?) (type-infer/term reified-term))
|
||||
#;(printf "Delta: ~s~nGamma: ~s~n" (delta) (gamma))
|
||||
(raise-syntax-error 'cur "term is ill-typed:" reified-term syn))
|
||||
(raise-curnel-type-error 'cur->datum reified-term syn))
|
||||
reified-term)
|
||||
|
||||
(define (datum->cur syn t)
|
||||
|
@ -224,42 +249,52 @@
|
|||
(term (reduce #,(delta) (subst-all #,(cur->datum syn) #,(first (bind-subst)) #,(second (bind-subst)))))))
|
||||
|
||||
;; Reflection tools
|
||||
;; TODO: Reflection tools should catch internal errors, e.g., from eval-cur et al. to
|
||||
;; ensure users can provide better error messages. But should not catch errors caused by user macros.
|
||||
|
||||
(define (cur-normalize syn)
|
||||
(datum->cur
|
||||
syn
|
||||
(eval-cur syn)))
|
||||
(define (local-env->gamma env)
|
||||
(for/fold ([gamma (gamma)])
|
||||
([(x t) (in-dict env)])
|
||||
(extend-Γ/syn (thunk gamma) x t)))
|
||||
|
||||
(define (cur-step syn)
|
||||
(define (normalize/syn syn #:local-env [env '()])
|
||||
(parameterize ([gamma (local-env->gamma env)])
|
||||
(datum->cur
|
||||
syn
|
||||
(eval-cur syn))))
|
||||
|
||||
(define (step/syn syn)
|
||||
(datum->cur
|
||||
syn
|
||||
(term (step ,(delta) ,(subst-bindings (cur->datum syn))))))
|
||||
|
||||
;; Are these two terms equivalent in type-systems internal equational reasoning?
|
||||
(define (cur-equal? e1 e2)
|
||||
(and (judgment-holds (convert ,(delta) ,(gamma) ,(eval-cur e1) ,(eval-cur e2))) #t))
|
||||
(and (judgment-holds (equivalent ,(delta) ,(eval-cur e1) ,(eval-cur e2))) #t))
|
||||
|
||||
;; TODO: Document local-env
|
||||
(define (cur-type-infer syn #:local-env [env '()])
|
||||
(parameterize ([gamma (for/fold ([gamma (gamma)])
|
||||
([(x t) (in-dict env)])
|
||||
(extend-Γ/syn (thunk gamma) x t))])
|
||||
(let ([t (type-infer/term (eval-cur syn))])
|
||||
(and t (datum->cur syn t)))))
|
||||
(define (type-infer/syn #:local-env [env '()] syn)
|
||||
(parameterize ([gamma (local-env->gamma env)])
|
||||
(with-handlers ([exn:cur:curnel:type? (lambda _ #f)])
|
||||
(let ([t (type-infer/term (eval-cur syn))])
|
||||
(and t (datum->cur syn t))))))
|
||||
|
||||
(define (cur-type-check? syn type)
|
||||
(type-check/term? (eval-cur syn) (eval-cur type)))
|
||||
(define (type-check/syn? syn type)
|
||||
(with-handlers ([exn:cur:curnel:type? (lambda _ #f)])
|
||||
(type-check/term? (eval-cur syn) (eval-cur type))))
|
||||
|
||||
;; Takes a Cur term syn and an arbitrary number of identifiers ls. The cur term is
|
||||
;; expanded until expansion reaches a Curnel form, or one of the
|
||||
;; identifiers in ls.
|
||||
(define (cur-expand syn . ls)
|
||||
(disarm
|
||||
(local-expand
|
||||
;; TODO: Holy crap boilerplate
|
||||
(define (cur-expand syn #:local-env [env '()] . ls)
|
||||
(parameterize ([gamma (local-env->gamma env)])
|
||||
(disarm
|
||||
(local-expand
|
||||
syn
|
||||
'expression
|
||||
(append (syntax-e #'(Type dep-inductive dep-lambda dep-app dep-elim dep-forall dep-top))
|
||||
ls)))))
|
||||
ls))))))
|
||||
|
||||
;; -----------------------------------------------------------------
|
||||
;; Require/provide macros
|
||||
|
@ -411,9 +446,8 @@
|
|||
;;
|
||||
;; TODO: Can these be simplified further?
|
||||
(define-syntax (dep-lambda syn)
|
||||
(syntax-parse syn
|
||||
#:datum-literals (:)
|
||||
[(_ (x:id : t) e)
|
||||
(syntax-case syn (:)
|
||||
[(_ (x : t) e)
|
||||
(syntax->curnel-syntax
|
||||
(quasisyntax/loc syn (λ (x : t) e)))]))
|
||||
|
||||
|
@ -424,32 +458,30 @@
|
|||
(quasisyntax/loc syn (#%app e1 e2)))]))
|
||||
|
||||
(define-syntax (dep-forall syn)
|
||||
(syntax-parse syn
|
||||
#:datum-literals (:)
|
||||
[(_ (x:id : t) e)
|
||||
(syntax-case syn (:)
|
||||
[(_ (x : t) e)
|
||||
(syntax->curnel-syntax
|
||||
(quasisyntax/loc syn (Π (x : t) e)))]))
|
||||
|
||||
(define-syntax (Type syn)
|
||||
(syntax-parse syn
|
||||
[(_ i:nat)
|
||||
(syntax-case syn ()
|
||||
[(_ i)
|
||||
(syntax->curnel-syntax
|
||||
(quasisyntax/loc syn (Unv i)))]
|
||||
[_ (quasisyntax/loc syn (Type 0))]))
|
||||
|
||||
(define-syntax (dep-inductive syn)
|
||||
(syntax-parse syn
|
||||
#:datum-literals (:)
|
||||
[(_ i:id : ti (x1:id : t1) ...)
|
||||
(syntax-case syn (:)
|
||||
[(_ i : ti (x1 : t1) ...)
|
||||
(begin
|
||||
(extend-Δ/syn! delta #'i #'ti #'((x1 : t1) ...))
|
||||
#'(void))]))
|
||||
|
||||
(define-syntax (dep-elim syn)
|
||||
(syntax-parse syn
|
||||
[(_ D:id motive (i ...) (m ...) e)
|
||||
(syntax-case syn ()
|
||||
[(_ D T)
|
||||
(syntax->curnel-syntax
|
||||
(quasisyntax/loc syn (elim D motive (i ...) (m ...) e)))]))
|
||||
(quasisyntax/loc syn (elim D T)))]))
|
||||
|
||||
(define-syntax-rule (dep-void) (void))
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
#lang s-exp syntax/module-reader
|
||||
cur
|
||||
cur/cur
|
||||
|
|
|
@ -1,16 +1,11 @@
|
|||
#lang s-exp "main.rkt"
|
||||
#lang s-exp "cur.rkt"
|
||||
;; Olly: The OTT-Like LibrarY
|
||||
;; TODO: Automagically create a parser from bnf grammar
|
||||
(require
|
||||
"stdlib/sugar.rkt"
|
||||
"stdlib/nat.rkt"
|
||||
;; TODO: "real-"? More like "curnel-"
|
||||
(only-in
|
||||
"main.rkt"
|
||||
[#%app real-app]
|
||||
[elim real-elim]
|
||||
[Π real-forall]
|
||||
[λ real-lambda]))
|
||||
(only-in "cur.rkt" [#%app real-app] [elim real-elim] [forall real-forall] [lambda real-lambda]))
|
||||
|
||||
(provide
|
||||
define-relation
|
||||
|
@ -32,7 +27,7 @@
|
|||
(coq-defns (format "~a~a~n" (coq-defns) str)))
|
||||
|
||||
(define (constructor-args syn)
|
||||
(syntax-parse (cur-type-infer syn)
|
||||
(syntax-parse (type-infer/syn syn)
|
||||
#:datum-literals (Π :)
|
||||
[(Π (x:id : t) body)
|
||||
(cons #'x (constructor-args #'body))]
|
||||
|
@ -48,67 +43,72 @@
|
|||
(define (cur->coq syn)
|
||||
(parameterize ([coq-defns ""])
|
||||
(define output
|
||||
(let cur->coq ([syn syn])
|
||||
(syntax-parse (cur-expand syn #'define #'begin)
|
||||
(let cur->coq ([syn syn]
|
||||
[local-env (make-immutable-hash)])
|
||||
(syntax-parse (cur-expand #:local-env local-env syn #'define #'begin)
|
||||
;; TODO: Need to add these to a literal set and export it
|
||||
;; Or, maybe overwrite syntax-parse
|
||||
#:literals (real-lambda real-forall data real-app real-elim define begin Type)
|
||||
[(begin e ...)
|
||||
(for/fold ([str ""])
|
||||
([e (syntax->list #'(e ...))])
|
||||
(format "~a~n" (cur->coq e)))]
|
||||
(format "~a~n" (cur->coq e local-env)))]
|
||||
[(define name:id body)
|
||||
(begin
|
||||
(coq-lift-top-level
|
||||
(format "Definition ~a := ~a.~n"
|
||||
(cur->coq #'name)
|
||||
(cur->coq #'body)))
|
||||
(cur->coq #'name local-env)
|
||||
(cur->coq #'body local-env)))
|
||||
"")]
|
||||
[(define (name:id (x:id : t) ...) body)
|
||||
(begin
|
||||
(define-values (args body-local-env)
|
||||
(for/fold ([str ""]
|
||||
[local-env local-env])
|
||||
([n (syntax->list #'(x ...))]
|
||||
[t (syntax->list #'(t ...))])
|
||||
(values
|
||||
(format
|
||||
"~a(~a : ~a) "
|
||||
str
|
||||
(cur->coq n local-env)
|
||||
(cur->coq t local-env))
|
||||
(dict-set local-env n t))))
|
||||
(coq-lift-top-level
|
||||
(format "Function ~a ~a := ~a.~n"
|
||||
(cur->coq #'name)
|
||||
(for/fold ([str ""])
|
||||
([n (syntax->list #'(x ...))]
|
||||
[t (syntax->list #'(t ...))])
|
||||
(format "~a(~a : ~a) " str (cur->coq n) (cur->coq t)))
|
||||
(cur->coq #'body)))
|
||||
(cur->coq #'name local-env)
|
||||
args
|
||||
(cur->coq #'body body-local-env)))
|
||||
"")]
|
||||
[(real-lambda ~! (x:id (~datum :) t) body:expr)
|
||||
(format "(fun ~a : ~a => ~a)" (cur->coq #'x) (cur->coq #'t)
|
||||
(cur->coq #'body))]
|
||||
(format "(fun ~a : ~a => ~a)" (syntax-e #'x) (cur->coq #'t local-env)
|
||||
(cur->coq #'body (dict-set local-env #'x #'t)))]
|
||||
[(real-forall ~! (x:id (~datum :) t) body:expr)
|
||||
(format "(forall ~a : ~a, ~a)" (syntax-e #'x) (cur->coq #'t)
|
||||
(cur->coq #'body))]
|
||||
(format "(forall ~a : ~a, ~a)" (syntax-e #'x) (cur->coq #'t local-env)
|
||||
(cur->coq #'body (dict-set local-env #'x #'t)))]
|
||||
[(data ~! n:id (~datum :) t (x*:id (~datum :) t*) ...)
|
||||
(begin
|
||||
(coq-lift-top-level
|
||||
(format "Inductive ~a : ~a :=~a."
|
||||
(sanitize-id (format "~a" (syntax-e #'n)))
|
||||
(cur->coq #'t)
|
||||
(for/fold ([strs ""])
|
||||
([clause (syntax->list #'((x* : t*) ...))])
|
||||
(syntax-parse clause
|
||||
[(x (~datum :) t)
|
||||
(format "~a~n| ~a : ~a" strs (syntax-e #'x)
|
||||
(cur->coq #'t))]))))
|
||||
(cur->coq #'t local-env)
|
||||
(call-with-values
|
||||
(thunk
|
||||
(for/fold ([strs ""]
|
||||
[local-env (dict-set local-env #'n #'t)])
|
||||
([x (attribute x*)]
|
||||
[t (attribute t*)])
|
||||
(values
|
||||
(format "~a~n| ~a : ~a" strs (syntax-e x)
|
||||
(cur->coq t local-env))
|
||||
(dict-set local-env x t))))
|
||||
(lambda (x y) x))))
|
||||
"")]
|
||||
[(Type i) "Type"]
|
||||
[(real-elim var:id motive (i ...) (m ...) d)
|
||||
(format
|
||||
"(~a_rect ~a~a~a ~a)"
|
||||
(cur->coq #'var)
|
||||
(cur->coq #'motive)
|
||||
(for/fold ([strs ""])
|
||||
([m (syntax->list #'(m ...))])
|
||||
(format "~a ~a" strs (cur->coq m)))
|
||||
(for/fold ([strs ""])
|
||||
([i (syntax->list #'(i ...))])
|
||||
(format "~a ~a" strs (cur->coq i)))
|
||||
(cur->coq #'d))]
|
||||
[(real-elim var t)
|
||||
(format "~a_rect" (cur->coq #'var local-env))]
|
||||
[(real-app e1 e2)
|
||||
(format "(~a ~a)" (cur->coq #'e1) (cur->coq #'e2))]
|
||||
(format "(~a ~a)" (cur->coq #'e1 local-env) (cur->coq #'e2 local-env))]
|
||||
[e:id (sanitize-id (format "~a" (syntax->datum #'e)))])))
|
||||
(format
|
||||
"~a~a"
|
||||
|
@ -206,6 +206,7 @@
|
|||
lab:rule-name
|
||||
(~var t (conclusion name indices (attribute lab))))
|
||||
#:with constr-decl
|
||||
;; TODO: quasisyntax/loc
|
||||
#'(lab : (-> h ... (t.name t.arg ...)))
|
||||
;; TODO: convert meta-vars such as e1 to e_1
|
||||
#:attr latex
|
||||
|
@ -288,7 +289,8 @@
|
|||
#:attr sym (syntax->datum #'x)
|
||||
#:fail-when (dict-has-key? (mv-map) (attribute sym)) #f
|
||||
#:attr constructor-name
|
||||
(format-id #'x "~a-~a" (lang-name) #'x)))
|
||||
(quasisyntax/loc #'x
|
||||
#,(format-id #'x "~a-~a" (lang-name) #'x))))
|
||||
|
||||
;; A terminal-args can appear as the argument to a terminal in
|
||||
;; an expression, or as a sub-expression in a terminal-args.
|
||||
|
@ -349,9 +351,9 @@
|
|||
(pattern
|
||||
e:meta-variable
|
||||
#:attr constructor-name
|
||||
(format-id #'e "~a->~a" #'e.type non-terminal-type)
|
||||
(quasisyntax/loc #'e #,(format-id #'e "~a->~a" #'e.type non-terminal-type))
|
||||
#:attr constr-decl
|
||||
#`(constructor-name : (-> e.type #,non-terminal-type))
|
||||
(quasisyntax/loc #'e (constructor-name : (-> e.type #,non-terminal-type)))
|
||||
#:attr latex
|
||||
(format "~a" (syntax-e #'e)))
|
||||
|
||||
|
@ -359,7 +361,7 @@
|
|||
(pattern
|
||||
x:terminal
|
||||
#:attr constr-decl
|
||||
#`(x.constructor-name : #,non-terminal-type)
|
||||
(quasisyntax/loc #'x (x.constructor-name : #,non-terminal-type))
|
||||
#:attr latex
|
||||
(format "~a" (syntax-e #'x)))
|
||||
|
||||
|
@ -367,7 +369,7 @@
|
|||
(pattern
|
||||
(x:terminal . (~var c (terminal-args non-terminal-type)))
|
||||
#:attr constr-decl
|
||||
#`(x.constructor-name : (-> #,@(attribute c.args) #,non-terminal-type))
|
||||
(quasisyntax/loc #'x (x.constructor-name : (-> #,@(attribute c.args) #,non-terminal-type)))
|
||||
#:attr latex
|
||||
(format "(~a ~a)" (syntax-e #'x) (attribute c.latex))))
|
||||
|
||||
|
@ -378,7 +380,7 @@
|
|||
(~optional (~datum ::=))
|
||||
;; Create a name for the type of this non-terminal, from the
|
||||
;; language name and the non-terminal name.
|
||||
(~bind [nt-type (format-id #'name "~a-~a" (lang-name) #'name)])
|
||||
(~bind [nt-type (quasisyntax/loc #'name #,(format-id #'name "~a-~a" (lang-name) #'name))])
|
||||
;; Imperatively update the map from meta-variables to the
|
||||
;; nt-type, to be used when generating the types of the constructors
|
||||
;; for this and later non-terminal.
|
||||
|
@ -387,7 +389,7 @@
|
|||
(~var c (expression (attribute nt-type))) ...)
|
||||
;; Generates the inductive data type for this non-terminal definition.
|
||||
#:attr def
|
||||
#`(data nt-type : Type c.constr-decl ...)
|
||||
(quasisyntax/loc #'name (data nt-type : Type c.constr-decl ...))
|
||||
#:attr latex
|
||||
(format
|
||||
"\\mbox{\\textit{~a}} & ~a & \\bnfdef & ~a\\\\~n"
|
||||
|
@ -435,7 +437,7 @@
|
|||
(dict-set! (mv-map) (syntax-e x) #'Nat)))])
|
||||
(syntax-parse #'non-terminal-defs
|
||||
[(def:non-terminal-def ...)
|
||||
(let ([output #`(begin def.def ...)])
|
||||
(let ([output (quasisyntax/loc #'name (begin def.def ...))])
|
||||
(when (attribute latex-file)
|
||||
(with-output-to-file (syntax-e #'latex-file)
|
||||
(thunk (typeset-bnf (attribute def.latex)))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(require "sugar.rkt")
|
||||
(provide Bool true false if not and or)
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(require
|
||||
"nat.rkt"
|
||||
"maybe.rkt"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(require "sugar.rkt")
|
||||
(provide Maybe none some some/i)
|
||||
|
||||
|
@ -9,5 +9,5 @@
|
|||
(define-syntax (some/i syn)
|
||||
(syntax-case syn ()
|
||||
[(_ a)
|
||||
(let ([a-ty (cur-type-infer #'a)])
|
||||
(let ([a-ty (type-infer/syn #'a)])
|
||||
#`(some #,a-ty a))]))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(require "sugar.rkt" "bool.rkt")
|
||||
;; TODO: override (all-defined-out) to enable exporting all these
|
||||
;; properly.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(require "sugar.rkt")
|
||||
;; TODO: Handle multiple provide forms properly
|
||||
;; TODO: Handle (all-defined-out) properly
|
||||
|
@ -31,8 +31,8 @@
|
|||
(define-syntax (conj/i syn)
|
||||
(syntax-case syn ()
|
||||
[(_ a b)
|
||||
(let ([a-type (cur-type-infer #'a)]
|
||||
[b-type (cur-type-infer #'b)])
|
||||
(let ([a-type (type-infer/syn #'a)]
|
||||
[b-type (type-infer/syn #'b)])
|
||||
#`(conj #,a-type #,b-type a b))]))
|
||||
|
||||
(define thm:and-is-symmetric
|
||||
|
@ -71,12 +71,11 @@
|
|||
(define proof:A-or-A
|
||||
(lambda (A : Type) (c : (Or A A))
|
||||
;; TODO: What should the motive be?
|
||||
(elim Or (lambda (A : Type) (B : Type) (c : (Or A B)) A)
|
||||
(A A)
|
||||
((lambda (A : Type) (B : Type) (a : A) a)
|
||||
;; TODO: How do we know B is A?
|
||||
(lambda (A : Type) (B : Type) (b : B) b))
|
||||
c)))
|
||||
(elim Or Type (lambda (A : Type) (B : Type) (c : (Or A B)) A)
|
||||
(lambda (A : Type) (B : Type) (a : A) a)
|
||||
;; TODO: How do we know B is A?
|
||||
(lambda (A : Type) (B : Type) (b : B) b)
|
||||
A A c)))
|
||||
|
||||
(qed thm:A-or-A proof:A-or-A)
|
||||
|#
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(provide
|
||||
->
|
||||
lambda
|
||||
|
@ -6,12 +6,10 @@
|
|||
[-> →]
|
||||
[-> forall]
|
||||
[-> ∀]
|
||||
[-> Π]
|
||||
[-> Pi]
|
||||
[lambda λ])
|
||||
#%app
|
||||
define
|
||||
:
|
||||
elim
|
||||
define-type
|
||||
match
|
||||
recur
|
||||
|
@ -27,37 +25,121 @@
|
|||
query-type)
|
||||
|
||||
(require
|
||||
(only-in "../main.rkt"
|
||||
(only-in "../cur.rkt"
|
||||
[elim real-elim]
|
||||
[#%app real-app]
|
||||
[λ real-lambda]
|
||||
[Π real-Π]
|
||||
[lambda real-lambda]
|
||||
[define real-define]))
|
||||
|
||||
;; Exceptions and such
|
||||
(begin-for-syntax
|
||||
(define-syntax-class result-type
|
||||
(pattern type:expr))
|
||||
(define-struct (exn:cur:type exn:cur) () #:transparent)
|
||||
|
||||
(define (deduce-type-infer-error-hints term)
|
||||
(syntax-parse term
|
||||
[x:id
|
||||
"; Seems to be an unbound variable"]
|
||||
[_ "could not infer a type."]))
|
||||
|
||||
(define (cur-type-infer-error-msg name v . other)
|
||||
(format
|
||||
"~aCur type error;~n Could not infer any type~a~n term: ~a~a"
|
||||
(if name (format "~a:" name) "")
|
||||
(deduce-type-infer-error-hints v)
|
||||
v
|
||||
(for/fold ([str ""])
|
||||
([other other])
|
||||
(format "~a~n context: ~a" str other))))
|
||||
|
||||
(define (raise-cur-type-infer-error . all)
|
||||
(raise
|
||||
(make-exn:cur:type
|
||||
(apply cur-type-infer-error-msg all)
|
||||
(current-continuation-marks)))))
|
||||
|
||||
(begin-for-syntax
|
||||
#| TODO
|
||||
| Design of "typed" macros for Cur.
|
||||
|
|
||||
| We can use syntax classes to emulate typed macros. The syntax
|
||||
| class calls the type-checker to ensure the term parsed term is
|
||||
| well-typed. This *must* not expand the the matched term as a side-effect.
|
||||
| Unfortunately, to handle binding, patterns that have variables
|
||||
| must thread binding information through while parsing in syntax
|
||||
| parse.
|
||||
| This can be handled by delaying the expansion and syntax-class
|
||||
| check until the term is under the binder; see delay-check macros.
|
||||
|
|
||||
|#
|
||||
(define-syntax-class cur-syntax
|
||||
(pattern e:expr))
|
||||
|
||||
(define-syntax-class well-typed-cur-term
|
||||
(pattern
|
||||
e:cur-syntax
|
||||
#:attr type (type-infer/syn #'e)
|
||||
#:fail-unless (attribute type)
|
||||
(cur-type-infer-error-msg #f #'e))))
|
||||
|
||||
;; For delaying a type-check until the term is under a binder
|
||||
;; NB: This is an impressively awesome solution..... need to write something about it.
|
||||
(define-syntax (delayed-check syn)
|
||||
(syntax-parse syn
|
||||
[(_ e:well-typed-cur-term) #'e]))
|
||||
|
||||
(begin-for-syntax
|
||||
(define-syntax-class parameter-declaration
|
||||
(pattern (name:id (~datum :) type:expr))
|
||||
#:commit
|
||||
(pattern
|
||||
(name:id (~datum :) ~! type:cur-syntax))
|
||||
|
||||
(pattern
|
||||
type:expr
|
||||
#:attr name (format-id #'type "~a" (gensym 'anon-parameter)))))
|
||||
type:cur-syntax
|
||||
#:attr name (format-id #'type "~a" (gensym 'anon-parameter))))
|
||||
|
||||
(define-syntax-class well-typed-parameter-declaration
|
||||
#:commit
|
||||
(pattern
|
||||
e:parameter-declaration
|
||||
#:attr type #'(delayed-check e.type)
|
||||
#:attr name #'e.name))
|
||||
|
||||
(define-syntax-class well-typed-argument-declaration
|
||||
#:commit
|
||||
(pattern
|
||||
;; TODO: Copy pasta from parameter-declaration
|
||||
(name:id (~datum :) ~! _type:cur-syntax)
|
||||
#:attr type #'(delayed-check _type)))
|
||||
|
||||
(define-syntax-class well-typed-parameter-list
|
||||
(pattern
|
||||
(d:well-typed-parameter-declaration ...+)
|
||||
#:attr names (attribute d.name)
|
||||
#:attr types (attribute d.type)))
|
||||
|
||||
(define-syntax-class well-typed-argument-list
|
||||
(pattern
|
||||
(d:well-typed-argument-declaration ...+)
|
||||
#:attr names (attribute d.name)
|
||||
#:attr types (attribute d.type))))
|
||||
|
||||
;; A multi-arity function type; takes parameter declaration of either
|
||||
;; a binding (name : type), or type whose name is generated.
|
||||
;; E.g.
|
||||
;; (-> (A : Type) A A)
|
||||
|
||||
(define-syntax (-> syn)
|
||||
(syntax-parse syn
|
||||
[(_ d:parameter-declaration ...+ result:result-type)
|
||||
[(_ d:parameter-declaration ...+ e:cur-syntax)
|
||||
#:with ds #'(d ...)
|
||||
#:declare ds well-typed-parameter-list
|
||||
(foldr (lambda (src name type r)
|
||||
(quasisyntax/loc src
|
||||
(real-Π (#,name : #,type) #,r)))
|
||||
#'result
|
||||
(attribute d)
|
||||
(attribute d.name)
|
||||
(attribute d.type))]))
|
||||
(forall (#,name : #,type) #,r)))
|
||||
#'(delayed-check e)
|
||||
(syntax->list (attribute ds))
|
||||
(attribute ds.names)
|
||||
(attribute ds.types))]))
|
||||
|
||||
;; TODO: Add forall macro that allows specifying *names*, with types
|
||||
;; inferred. unlike -> which require types but not names
|
||||
|
@ -66,94 +148,76 @@
|
|||
|
||||
;; TODO: Allows argument-declarations to have types inferred, similar
|
||||
;; to above TODO forall
|
||||
(begin-for-syntax
|
||||
;; eta-expand syntax-class for error messages
|
||||
(define-syntax-class argument-declaration
|
||||
(pattern
|
||||
e:parameter-declaration
|
||||
#:attr name #'e.name
|
||||
#:attr type #'e.type)))
|
||||
(define-syntax (lambda syn)
|
||||
(syntax-parse syn
|
||||
[(_ d:argument-declaration ...+ body:expr)
|
||||
[(_ d:parameter-declaration ...+ e:cur-syntax)
|
||||
#:with ds #'(d ...)
|
||||
#:declare ds well-typed-argument-list
|
||||
(foldr (lambda (src name type r)
|
||||
(quasisyntax/loc src
|
||||
(real-lambda (#,name : #,type) #,r)))
|
||||
#'body
|
||||
(attribute d)
|
||||
(attribute d.name)
|
||||
(attribute d.type))]))
|
||||
#'(delayed-check e)
|
||||
(syntax->list (attribute ds))
|
||||
(attribute ds.names)
|
||||
(attribute ds.types))]))
|
||||
|
||||
(begin-for-syntax
|
||||
(define-syntax-class forall-type
|
||||
(pattern
|
||||
((~literal forall) ~! (parameter-name:id (~datum :) parameter-type) body)))
|
||||
|
||||
(define-syntax-class well-typed-cur-function
|
||||
(pattern
|
||||
e:well-typed-cur-term
|
||||
#:attr type (attribute e.type)
|
||||
#:fail-unless (syntax-parse (attribute e.type)
|
||||
[t:forall-type #t]
|
||||
[_ #f])
|
||||
(format
|
||||
"Expected ~a to be a function, but inferred type ~a"
|
||||
(syntax->datum #'e)
|
||||
(syntax->datum (attribute e.type))))))
|
||||
|
||||
;; TODO: This makes for really bad error messages when an identifier is undefined.
|
||||
(define-syntax (#%app syn)
|
||||
(syntax-case syn ()
|
||||
[(_ e)
|
||||
(quasisyntax/loc syn e)]
|
||||
[(_ e1 e2)
|
||||
(quasisyntax/loc syn
|
||||
(real-app e1 e2))]
|
||||
[(_ e1 e2 e3 ...)
|
||||
(quasisyntax/loc syn
|
||||
(#%app (#%app e1 e2) e3 ...))]))
|
||||
(syntax-parse syn
|
||||
[(_ f:well-typed-cur-function ~! e:well-typed-cur-term ...+)
|
||||
;; Have to thread each argument through, to handle dependency.
|
||||
(for/fold ([type (attribute f.type)])
|
||||
([arg (attribute e)]
|
||||
[inferred-type (attribute e.type)])
|
||||
(define/syntax-parse expected:forall-type type)
|
||||
(define expected-type (attribute expected.parameter-type))
|
||||
(unless (type-check/syn? arg expected-type)
|
||||
(raise-syntax-error
|
||||
'#%app
|
||||
(format
|
||||
"Expected ~a to have type ~a, but inferred type ~a."
|
||||
(syntax->datum arg)
|
||||
(syntax->datum expected-type)
|
||||
(syntax->datum inferred-type))
|
||||
syn
|
||||
arg))
|
||||
(normalize/syn
|
||||
#`(real-app
|
||||
(real-lambda (expected.parameter-name : expected.parameter-type)
|
||||
expected.body)
|
||||
#,arg)))
|
||||
(for/fold ([app (quasisyntax/loc syn
|
||||
(real-app f #,(first (attribute e))))])
|
||||
([arg (rest (attribute e))])
|
||||
(quasisyntax/loc arg
|
||||
(real-app #,app #,arg)))]))
|
||||
|
||||
(define-syntax define-type
|
||||
(syntax-rules ()
|
||||
[(_ (name (a : t) ...) body)
|
||||
(define name (-> (a : t) ... body))]
|
||||
(define name (forall (a : t) ... body))]
|
||||
[(_ name type)
|
||||
(define name type)]))
|
||||
|
||||
;; Cooperates with define to allow Haskell-esque type annotations
|
||||
#| TODO NB:
|
||||
| This method of cooperating macros is sort of a terrible
|
||||
| hack. Instead, need principled way of adding/retrieving information
|
||||
| to/from current module. E.g. perhaps provide extensions an interface to
|
||||
| module's term environment and inductive signature. Then, :: could add
|
||||
| new "id : type" to environment, and define could extract type and use.
|
||||
|#
|
||||
(begin-for-syntax
|
||||
(define annotation-dict (make-hash))
|
||||
(define (annotation->types type-syn)
|
||||
(let loop ([ls '()]
|
||||
[syn type-syn])
|
||||
(syntax-parse (cur-expand syn)
|
||||
#:datum-literals (:)
|
||||
[(real-Π (x:id : type) body)
|
||||
(loop (cons #'type ls) #'body)]
|
||||
[_ (reverse ls)]))))
|
||||
|
||||
(define-syntax (: syn)
|
||||
(syntax-parse syn
|
||||
[(_ name:id type:expr)
|
||||
;; NB: Unhygenic; need to reuse Racket's identifiers, and make this type annotation a syntax property
|
||||
(syntax-parse (cur-expand #'type)
|
||||
#:datum-literals (:)
|
||||
[(real-Π (x:id : type) body) (void)]
|
||||
[_
|
||||
(raise-syntax-error
|
||||
':
|
||||
"Can only declare annotations for functions, but not a function type"
|
||||
syn)])
|
||||
(dict-set! annotation-dict (syntax->datum #'name) (annotation->types #'type))
|
||||
#'(void)]))
|
||||
|
||||
;; TODO: Allow inferring types as in above TODOs for lambda, forall
|
||||
(define-syntax (define syn)
|
||||
(syntax-parse syn
|
||||
#:datum-literals (:)
|
||||
[(define (name:id x:id ...) body)
|
||||
(cond
|
||||
[(dict-ref annotation-dict (syntax->datum #'name)) =>
|
||||
(lambda (anns)
|
||||
(quasisyntax/loc syn
|
||||
(real-define name (lambda #,@(for/list ([x (syntax->list #'(x ...))]
|
||||
[type anns])
|
||||
#`(#,x : #,type)) body))))]
|
||||
[else
|
||||
(raise-syntax-error
|
||||
'define
|
||||
"Cannot omit type annotations unless you have declared them with (: name type) form first."
|
||||
syn)])]
|
||||
(syntax-case syn ()
|
||||
[(define (name (x : t) ...) body)
|
||||
(quasisyntax/loc syn
|
||||
(real-define name (lambda (x : t) ... body)))]
|
||||
|
@ -161,72 +225,22 @@
|
|||
(quasisyntax/loc syn
|
||||
(real-define id body))]))
|
||||
|
||||
#|
|
||||
(begin-for-syntax
|
||||
(define (type->telescope syn)
|
||||
(syntax-parse (cur-expand syn)
|
||||
#:literals (real-Π)
|
||||
#:datum-literals (:)
|
||||
[(real-Π (x:id : t) body)
|
||||
(cons #'(x : t) (type->telescope #'body))]
|
||||
[_ '()]))
|
||||
|
||||
(define (type->body syn)
|
||||
(syntax-parse syn
|
||||
#:literals (real-Π)
|
||||
#:datum-literals (:)
|
||||
[(real-Π (x:id : t) body)
|
||||
(type->body #'body)]
|
||||
[e #'e]))
|
||||
|
||||
(define (constructor-indices D syn)
|
||||
(let loop ([syn syn]
|
||||
[args '()])
|
||||
(syntax-parse (cur-expand syn)
|
||||
#:literals (real-app)
|
||||
[D:id args]
|
||||
[(real-app e1 e2)
|
||||
(loop #'e1 (cons #'e2 args))])))
|
||||
|
||||
(define (inductive-index-telescope D)
|
||||
(type->telescope (cur-type-infer D)))
|
||||
|
||||
(define (inductive-method-telescope D motive)
|
||||
(for/list ([syn (cur-constructor-map D)])
|
||||
(with-syntax ([(c : t) syn]
|
||||
[name (gensym (format-symbol "~a-~a" #'c 'method))]
|
||||
[((arg : arg-type) ...) (type->telescope #'t)]
|
||||
[((rarg : rarg-type) ...) (constructor-recursive-args D #'((arg : arg-type) ...))]
|
||||
[((ih : ih-type) ...) (constructor-inductive-hypotheses #'((rarg : rarg-type) ...) motive)]
|
||||
[(iarg ...) (constructor-indices D (type->body #'t))]
|
||||
)
|
||||
#`(name : (forall (arg : arg-type) ...
|
||||
(ih : ih-type) ...
|
||||
(motive iarg ...)))))))
|
||||
|
||||
(define-syntax (elim syn)
|
||||
(syntax-parse syn
|
||||
[(elim D:id U e ...)
|
||||
(with-syntax ([((x : t) ...) (inductive-index-telescope #'D)]
|
||||
[motive (gensym 'motive)]
|
||||
[y (gensym 'y)]
|
||||
[disc (gensym 'disc)]
|
||||
[((method : method-type) ...) (inductive-method-telescope #'D #'motive)])
|
||||
#`((lambda
|
||||
(motive : (forall (x : t) ... (y : (D x ...)) U))
|
||||
(method : ) ...
|
||||
(x : t) ...
|
||||
(disc : (D x ...)) ...
|
||||
(real-elim D motive (x ...) (method ...) disc))
|
||||
e ...)
|
||||
)
|
||||
]))
|
||||
|#
|
||||
[(_ t1 t2 e ...)
|
||||
(maybe-cur-apply
|
||||
#`(real-elim t1 t2)
|
||||
(attribute e))]))
|
||||
|
||||
;; Quite fragie to give a syntactic treatment of pattern matching -> eliminator. Replace with "Elimination with a Motive"
|
||||
(begin-for-syntax
|
||||
(define ih-dict (make-hash))
|
||||
|
||||
(define (maybe-cur-apply f ls)
|
||||
(if (null? ls)
|
||||
f
|
||||
#`(#,f #,@ls)))
|
||||
|
||||
(define-syntax-class curried-application
|
||||
(pattern
|
||||
((~literal real-app) name:id e:expr)
|
||||
|
@ -249,6 +263,10 @@
|
|||
#'x
|
||||
#:attr indices
|
||||
'()
|
||||
#:attr names
|
||||
'()
|
||||
#:attr types
|
||||
'()
|
||||
#:attr decls
|
||||
(list #`(#,(gensym 'anon-discriminant) : x))
|
||||
#:attr abstract-indices
|
||||
|
@ -268,7 +286,7 @@
|
|||
#:attr types
|
||||
;; TODO: Detect failure, report error/suggestions
|
||||
(for/list ([e (attribute indices)])
|
||||
(or (cur-type-infer e)
|
||||
(or (type-infer/syn e)
|
||||
(raise-syntax-error
|
||||
'match
|
||||
(format
|
||||
|
@ -289,15 +307,21 @@
|
|||
(lambda (return)
|
||||
;; NB: unhygenic
|
||||
;; Normalize at compile-time, for efficiency at run-time
|
||||
(cur-normalize
|
||||
#`((lambda
|
||||
;; TODO: utteraly fragile; relines on the indices being referred to by name, not computed
|
||||
;; works only for simple type familes and simply matches on them
|
||||
#,@(for/list ([name (attribute indices)]
|
||||
[type (attribute types)])
|
||||
#`(#,name : #,type))
|
||||
#,return)
|
||||
#,@(attribute names))))))
|
||||
(normalize/syn
|
||||
#:local-env
|
||||
(for/fold ([d (make-immutable-hash)])
|
||||
([name (attribute names)]
|
||||
[type (attribute types)])
|
||||
(dict-set d name type))
|
||||
(maybe-cur-apply
|
||||
#`(lambda
|
||||
;; TODO: utteraly fragile; relines on the indices being referred to by name, not computed
|
||||
;; works only for simple type familes and simply matches on them
|
||||
#,@(for/list ([name (attribute indices)]
|
||||
[type (attribute types)])
|
||||
#`(#,name : #,type))
|
||||
#,return)
|
||||
(attribute names))))))
|
||||
|
||||
;; todo: Support just names, inferring types
|
||||
(define-syntax-class match-declaration
|
||||
|
@ -340,19 +364,26 @@
|
|||
#:attr decls
|
||||
;; Infer the inductive hypotheses, add them to the pattern decls
|
||||
;; and update the dictionarty for the recur form
|
||||
(for/fold ([decls (attribute d.decls)])
|
||||
([type-syn (attribute d.types)]
|
||||
[name-syn (attribute d.names)]
|
||||
[src (attribute d.decls)]
|
||||
;; NB: Non-hygenic
|
||||
;; BUG TODO: This fails when D is an inductive applied to arguments...
|
||||
#:when (cur-equal? type-syn D))
|
||||
(define/syntax-parse type:inductive-type-declaration (cur-expand type-syn))
|
||||
(let ([ih-name (quasisyntax/loc src #,(format-id name-syn "ih-~a" name-syn))]
|
||||
;; Normalize at compile-time, for efficiency at run-time
|
||||
[ih-type (cur-normalize #`(#,motive #,@(attribute type.indices) #,name-syn))])
|
||||
(dict-set! ih-dict (syntax->datum name-syn) ih-name)
|
||||
(append decls (list #`(#,ih-name : #,ih-type)))))))
|
||||
(call-with-values
|
||||
(thunk
|
||||
(for/fold ([decls (attribute d.decls)]
|
||||
[local-env (attribute d.local-env)])
|
||||
([type-syn (attribute d.types)]
|
||||
[name-syn (attribute d.names)]
|
||||
[src (attribute d.decls)]
|
||||
;; NB: Non-hygenic
|
||||
;; BUG TODO: This fails when D is an inductive applied to arguments...
|
||||
#:when (cur-equal? type-syn D))
|
||||
(define/syntax-parse type:inductive-type-declaration (cur-expand type-syn))
|
||||
(let ([ih-name (quasisyntax/loc src #,(format-id name-syn "ih-~a" name-syn))]
|
||||
;; Normalize at compile-time, for efficiency at run-time
|
||||
[ih-type (normalize/syn #:local-env local-env
|
||||
(maybe-cur-apply motive
|
||||
(append (attribute type.indices) (list name-syn))))])
|
||||
(dict-set! ih-dict (syntax->datum name-syn) ih-name)
|
||||
(values (append decls (list #`(#,ih-name : #,ih-type)))
|
||||
(dict-set local-env ih-name ih-type)))))
|
||||
(lambda (x y) x))))
|
||||
|
||||
(define-syntax-class (match-preclause maybe-return-type)
|
||||
(pattern
|
||||
|
@ -362,7 +393,7 @@
|
|||
(or maybe-return-type
|
||||
;; Ignore errors when trying to infer this type; other attempt might succeed
|
||||
(with-handlers ([values (lambda _ #f)])
|
||||
(cur-type-infer #:local-env (attribute p.local-env) #'b)))))
|
||||
(type-infer/syn #:local-env (attribute p.local-env) #'b)))))
|
||||
|
||||
(define-syntax-class (match-clause D motive)
|
||||
(pattern
|
||||
|
@ -391,6 +422,8 @@
|
|||
(syntax->datum #'id))
|
||||
syn)))]))
|
||||
|
||||
;; TODO: Better error messages; follow pattern of -> and lambda etc to first parse, then type-check.
|
||||
;; TODO: Deprecate #:local-env
|
||||
(define-syntax (match syn)
|
||||
(syntax-parse syn
|
||||
[(_ d
|
||||
|
@ -398,7 +431,7 @@
|
|||
(~optional
|
||||
(~seq #:in ~! t)
|
||||
#:defaults
|
||||
([t (or (cur-type-infer #'d)
|
||||
([t (or (type-infer/syn #'d)
|
||||
(raise-syntax-error
|
||||
'match
|
||||
"Could not infer discrimnant's type. Try using #:in to declare it."
|
||||
|
@ -423,9 +456,15 @@
|
|||
(quasisyntax/loc syn
|
||||
(elim
|
||||
D.inductive-name
|
||||
#,(or
|
||||
(type-infer/syn (attribute return-type))
|
||||
(raise-syntax-error
|
||||
'match
|
||||
"Could not infer type of motive. Sorry, you'll have to use elim."
|
||||
syn))
|
||||
motive
|
||||
#,(attribute D.indices)
|
||||
(c.method ...)
|
||||
c.method ...
|
||||
#,@(attribute D.indices)
|
||||
d))]))
|
||||
|
||||
(begin-for-syntax
|
||||
|
@ -437,14 +476,14 @@
|
|||
#:attr type (cond
|
||||
[(attribute t)
|
||||
;; TODO: Code duplication in ::
|
||||
(unless (cur-type-check? #'e #'t)
|
||||
(unless (type-check/syn? #'e #'t)
|
||||
(raise-syntax-error
|
||||
'let
|
||||
(format "Term ~a does not have expected type ~a. Inferred type was ~a"
|
||||
(cur->datum #'e) (cur->datum #'t) (cur->datum (cur-type-infer #'e)))
|
||||
(cur->datum #'e) (cur->datum #'t) (cur->datum (type-infer/syn #'e)))
|
||||
#'e (quasisyntax/loc #'x (x e))))
|
||||
#'t]
|
||||
[(cur-type-infer #'e)]
|
||||
[(type-infer/syn #'e)]
|
||||
[else
|
||||
(raise-syntax-error
|
||||
'let
|
||||
|
@ -455,29 +494,29 @@
|
|||
[(let (c:let-clause ...) body)
|
||||
#'((lambda (c.id : c.type) ... body) c.e ...)]))
|
||||
|
||||
;; Normally type checking will only happen if a term is actually used/appears at top-level.
|
||||
;; This forces a term to be checked against a particular type.
|
||||
;; Normally type checking will only happen if a term is actually used. This forces a term to be
|
||||
;; checked against a particular type.
|
||||
(define-syntax (:: syn)
|
||||
(syntax-case syn ()
|
||||
[(_ pf t)
|
||||
(begin
|
||||
;; TODO: Code duplication in let-clause pattern
|
||||
(unless (cur-type-check? #'pf #'t)
|
||||
(unless (type-check/syn? #'pf #'t)
|
||||
(raise-syntax-error
|
||||
'::
|
||||
(format "Term ~a does not have expected type ~a. Inferred type was ~a"
|
||||
(cur->datum #'pf) (cur->datum #'t) (cur->datum (cur-type-infer #'pf)))
|
||||
(cur->datum #'pf) (cur->datum #'t) (cur->datum (type-infer/syn #'pf)))
|
||||
syn))
|
||||
#'(void))]))
|
||||
|
||||
(define-syntax (run syn)
|
||||
(syntax-case syn ()
|
||||
[(_ expr) (cur-normalize #'expr)]))
|
||||
[(_ expr) (normalize/syn #'expr)]))
|
||||
|
||||
(define-syntax (step syn)
|
||||
(syntax-case syn ()
|
||||
[(_ expr)
|
||||
(let ([t (cur-step #'expr)])
|
||||
(let ([t (step/syn #'expr)])
|
||||
(displayln (cur->datum t))
|
||||
t)]))
|
||||
|
||||
|
@ -493,6 +532,6 @@
|
|||
(syntax-case syn ()
|
||||
[(_ term)
|
||||
(begin
|
||||
(printf "\"~a\" has type \"~a\"~n" (syntax->datum #'term) (syntax->datum (cur-type-infer #'term)))
|
||||
(printf "\"~a\" has type \"~a\"~n" (syntax->datum #'term) (syntax->datum (type-infer/syn #'term)))
|
||||
;; Void is undocumented and a hack, but sort of works
|
||||
#'(void))]))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../../main.rkt"
|
||||
#lang s-exp "../../cur.rkt"
|
||||
(require
|
||||
(for-syntax racket/syntax))
|
||||
(provide
|
||||
|
@ -220,7 +220,7 @@
|
|||
[pf (proof-state-proof ps)])
|
||||
(unless (proof-state-proof-complete? ps)
|
||||
(raise-syntax-error 'qed "Proof contains holes" (pf (current-hole-pretty-symbol))))
|
||||
(unless (cur-type-check? pf t)
|
||||
(unless (type-check/syn? pf t)
|
||||
(raise-syntax-error 'qed "Invalid proof" pf t))
|
||||
pf)))
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../../main.rkt"
|
||||
#lang s-exp "../../cur.rkt"
|
||||
(require
|
||||
"base.rkt"
|
||||
(prefix-in basic: "standard.rkt")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../../main.rkt"
|
||||
#lang s-exp "../../cur.rkt"
|
||||
(require
|
||||
"base.rkt"
|
||||
(for-syntax racket/syntax))
|
||||
|
@ -22,7 +22,7 @@
|
|||
[(forall (x:id : P:expr) body:expr)
|
||||
(let* ([ps (proof-state-extend-env ps name #'P)]
|
||||
[ps (proof-state-current-goal-set ps #'body)]
|
||||
[ps (proof-state-fill-proof-hole ps (lambda (x) #`(λ (#,name : P) #,x)))])
|
||||
[ps (proof-state-fill-proof-hole ps (lambda (x) #`(lambda (#,name : P) #,x)))])
|
||||
ps)]
|
||||
[_ (error 'intro "Can only intro when current goal is of the form (∀ (x : P) body)")]))
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#lang s-exp "../main.rkt"
|
||||
#lang s-exp "../cur.rkt"
|
||||
(require
|
||||
"nat.rkt"
|
||||
"bool.rkt"
|
||||
|
@ -38,7 +38,7 @@
|
|||
#`(define-syntax (#,name syn)
|
||||
(syntax-case syn ()
|
||||
[(_ arg args (... ...))
|
||||
#`(#,(format-id syn "~a-~a" '#,name (cur-type-infer #'arg))
|
||||
#`(#,(format-id syn "~a-~a" '#,name (type-infer/syn #'arg))
|
||||
arg
|
||||
args (... ...))]))))]))
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
|||
#`(begin
|
||||
#,@(for/list ([def (syntax->list #'(defs ...))])
|
||||
(let-values ([(name body) (process-def def)])
|
||||
(unless (cur-type-check?
|
||||
(unless (type-check/syn?
|
||||
body
|
||||
#`(#,(dict-ref
|
||||
(dict-ref typeclasses (syntax->datum #'class))
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
(define deps '("base" ("redex-lib" #:version "1.11")))
|
||||
(define build-deps '())
|
||||
(define pkg-desc "implementation (no documentation, tests) part of \"cur\".")
|
||||
(define version "0.4")
|
||||
(define version "0.2")
|
||||
(define pkg-authors '(wilbowma))
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
(require
|
||||
rackunit
|
||||
cur/stdlib/sugar
|
||||
cur/stdlib/nat
|
||||
cur/stdlib/bool
|
||||
cur/stdlib/prop
|
||||
cur/olly)
|
||||
|
||||
(begin-for-syntax
|
||||
|
@ -30,29 +33,28 @@
|
|||
"(forall .+ : Type, Type)"
|
||||
(cur->coq #'(-> Type Type)))
|
||||
(let ([t (cur->coq
|
||||
#'(define-relation (meow gamma term type)
|
||||
[(g : gamma) (e : term) (t : type)
|
||||
#'(define-relation (meow Nat Bool Nat)
|
||||
[(n : Nat) (b : Bool) (m : Nat)
|
||||
--------------- T-Bla
|
||||
(meow g e t)]))])
|
||||
(meow n b m)]))])
|
||||
(check-regexp-match
|
||||
"Inductive meow : \\(forall .+ : gamma, \\(forall .+ : term, \\(forall .+ : type, Type\\)\\)\\) :="
|
||||
"Inductive meow : \\(forall .+ : Nat, \\(forall .+ : Bool, \\(forall .+ : Nat, Type\\)\\)\\) :="
|
||||
(first (string-split t "\n")))
|
||||
(check-regexp-match
|
||||
"\\| T-Bla : \\(forall g : gamma, \\(forall e : term, \\(forall t : type, \\(\\(\\(meow g\\) e\\) t\\)\\)\\)\\)\\."
|
||||
"\\| T-Bla : \\(forall n : Nat, \\(forall b : Bool, \\(forall m : Nat, \\(\\(\\(meow n\\) b\\) m\\)\\)\\)\\)\\."
|
||||
(second (string-split t "\n"))))
|
||||
(let ([t (cur->coq
|
||||
#'(elim nat (lambda (x : nat) nat)
|
||||
()
|
||||
(z (lambda (x : nat) (ih-x : nat) ih-x))
|
||||
e))])
|
||||
#'(elim Nat Type (lambda (x : Nat) Nat) z
|
||||
(lambda (x : Nat) (ih-x : Nat) ih-x)
|
||||
z))])
|
||||
(check-regexp-match
|
||||
"\\(nat_rect \\(fun x : nat => nat\\) z \\(fun x : nat => \\(fun ih_x : nat => ih_x\\)\\) e\\)"
|
||||
"\\(\\(\\(\\(Nat_rect \\(fun x : Nat => Nat\\)\\) z\\) \\(fun x : Nat => \\(fun ih_x : Nat => ih_x\\)\\)\\) z\\)"
|
||||
t))
|
||||
(check-regexp-match
|
||||
"Definition thm_plus_commutes := \\(forall n : nat, \\(forall m : nat, \\(\\(\\(== nat\\) \\(\\(plus n\\) m\\)\\) \\(\\(plus m\\) n\\)\\)\\)\\).\n"
|
||||
"Definition thm_plus_commutes := \\(forall n : Nat, \\(forall m : Nat, \\(\\(\\(== Nat\\) \\(\\(plus n\\) m\\)\\) \\(\\(plus m\\) n\\)\\)\\)\\).\n"
|
||||
(cur->coq
|
||||
#'(define thm:plus-commutes (forall (n : nat) (m : nat)
|
||||
(== nat (plus n m) (plus m n))))))
|
||||
#'(define thm:plus-commutes (forall (n : Nat) (m : Nat)
|
||||
(== Nat (plus n m) (plus m n))))))
|
||||
(check-regexp-match
|
||||
"Function add1 \\(n : nat\\) := \\(s n\\).\n"
|
||||
(cur->coq #'(define (add1 (n : nat)) (s n)))))
|
||||
"Function add1 \\(n : Nat\\) := \\(s n\\).\n"
|
||||
(cur->coq #'(define (add1 (n : Nat)) (s n)))))
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
#lang cur
|
||||
|
||||
(require
|
||||
cur/stdlib/sugar
|
||||
rackunit)
|
||||
|
||||
(data Nat : Type
|
||||
(z : Nat)
|
||||
(s : (Π (x : Nat) Nat)))
|
||||
|
||||
(plus . : . (-> Nat Nat Nat))
|
||||
(define (plus n m)
|
||||
(match n
|
||||
[z m]
|
||||
[(s (x : Nat))
|
||||
(s (recur x))]))
|
||||
|
||||
(check-equal?
|
||||
(plus z z)
|
||||
z)
|
||||
|
||||
(check-equal?
|
||||
(plus (s z) z)
|
||||
(s z))
|
|
@ -81,6 +81,23 @@
|
|||
(Π (a : S) (Π (b : B) ((and S) B)))
|
||||
(subst (Π (a : A) (Π (b : B) ((and A) B))) A S))))
|
||||
|
||||
;; Various accessor tests
|
||||
;; ------------------------------------------------------------------------
|
||||
|
||||
(check-equal?
|
||||
(term (Δ-key-by-constructor ,Δ zero))
|
||||
(term nat))
|
||||
(check-equal?
|
||||
(term (Δ-key-by-constructor ,Δ s))
|
||||
(term nat))
|
||||
|
||||
(check-equal?
|
||||
(term (Δ-ref-constructor-map ,Δ nat))
|
||||
(term ((zero : nat) (s : (Π (x : nat) nat)))))
|
||||
(check-equal?
|
||||
(term (Δ-ref-constructor-map ,sigma false))
|
||||
(term ()))
|
||||
|
||||
;; Telescope tests
|
||||
;; ------------------------------------------------------------------------
|
||||
;; Are these telescopes the same when filled with alpha-equivalent, and equivalently renamed, termed
|
||||
|
@ -98,10 +115,41 @@
|
|||
(term (Δ-ref-parameter-Ξ ,Δ4 and))
|
||||
(term (Π (A : Type) (Π (B : Type) hole))))
|
||||
|
||||
(check-telescope-equiv?
|
||||
(term (Ξ-compose
|
||||
(Π (x : t_0) (Π (y : t_1) hole))
|
||||
(Π (z : t_2) (Π (a : t_3) hole))))
|
||||
(term (Π (x : t_0) (Π (y : t_1) (Π (z : t_2) (Π (a : t_3) hole))))))
|
||||
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-methods-telescope ,Δ nat (λ (x : nat) nat)))
|
||||
(term (Π (m-zero : ((λ (x : nat) nat) zero))
|
||||
(Π (m-s : (Π (x : nat) (Π (x-ih : ((λ (x : nat) nat) x)) ((λ (x : nat) nat) (s x))))) hole))))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-methods-telescope ,Δ nat P))
|
||||
(term (Π (m-zero : (P zero))
|
||||
(Π (m-s : (Π (x : nat) (Π (ih-x : (P x)) (P (s x)))))
|
||||
hole))))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-methods-telescope ,Δ nat (λ (x : nat) nat)))
|
||||
(term (Π (m-zero : ((λ (x : nat) nat) zero))
|
||||
(Π (m-s : (Π (x : nat) (Π (ih-x : ((λ (x : nat) nat) x)) ((λ (x : nat) nat) (s x)))))
|
||||
hole))))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-methods-telescope ,Δ4 and (λ (A : Type) (λ (B : Type) (λ (x : ((and A) B)) true)))))
|
||||
(term (Π (m-conj : (Π (A : Type) (Π (B : Type) (Π (a : A) (Π (b : B)
|
||||
((((λ (A : Type) (λ (B : Type) (λ (x : ((and A) B)) true)))
|
||||
A)
|
||||
B)
|
||||
((((conj A) B) a) b)))))))
|
||||
hole)))
|
||||
(check-true (x? (term false)))
|
||||
(check-true (Ξ? (term hole)))
|
||||
(check-true (t? (term (λ (y : false) (Π (x : Type) x)))))
|
||||
(check-true (redex-match? ttL ((x : t) ...) (term ())))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-methods-telescope ,sigma false (λ (y : false) (Π (x : Type) x))))
|
||||
(term hole))
|
||||
|
||||
;; Tests for inductive elimination
|
||||
;; ------------------------------------------------------------------------
|
||||
|
@ -109,32 +157,21 @@
|
|||
(check-true
|
||||
(redex-match? tt-ctxtL (in-hole Θ_i (hole (in-hole Θ_r zero))) (term (hole zero))))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-inductive-elim ,Δ nat
|
||||
(elim nat (λ (x : nat) nat) ()
|
||||
((s zero) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
hole)
|
||||
(term (Δ-inductive-elim ,Δ nat Type (λ (x : nat) nat) hole
|
||||
((hole (s zero)) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(hole zero)))
|
||||
(term (hole (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
zero))))
|
||||
(term (hole (((((elim nat Type) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
zero))))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-inductive-elim ,Δ nat
|
||||
(elim nat (λ (x : nat) nat) ()
|
||||
((s zero) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
hole)
|
||||
(term (Δ-inductive-elim ,Δ nat Type (λ (x : nat) nat) hole
|
||||
((hole (s zero)) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(hole (s zero))))
|
||||
(term (hole (elim nat (λ (x : nat) nat) ()
|
||||
((s zero) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(s zero)))))
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-inductive-elim ,Δ nat
|
||||
(elim nat (λ (x : nat) nat) ()
|
||||
((s zero) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
hole)
|
||||
hole))
|
||||
(term hole))
|
||||
(term (hole (((((elim nat Type) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(s zero)))))
|
||||
|
||||
;; Tests for dynamic semantics
|
||||
;; ------------------------------------------------------------------------
|
||||
|
@ -142,8 +179,6 @@
|
|||
(check-true (v? (term (λ (x_0 : (Unv 0)) x_0))))
|
||||
(check-true (v? (term (refl Nat))))
|
||||
(check-true (v? (term ((refl Nat) z))))
|
||||
(check-true (v? (term zero)))
|
||||
(check-true (v? (term (s zero))))
|
||||
|
||||
;; TODO: Move equivalence up here, and use in these tests.
|
||||
(check-equiv? (term (reduce ∅ (Unv 0))) (term (Unv 0)))
|
||||
|
@ -153,71 +188,63 @@
|
|||
(term (Π (x : t) (Unv 0))))
|
||||
(check-not-equiv? (term (reduce ∅ (Π (x : t) ((Π (x_0 : t) (x_0 x)) x))))
|
||||
(term (Π (x : t) (x x))))
|
||||
|
||||
(check-equal? (term (Δ-constructor-index ,Δ nat zero)) 0)
|
||||
(check-equiv? (term (reduce ,Δ (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
zero)))
|
||||
(check-equiv? (term (reduce ,Δ (((((elim nat Type) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat)
|
||||
(s (s x)))))
|
||||
zero)))
|
||||
(term (s zero)))
|
||||
(check-equiv? (term (reduce ,Δ (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(s zero))))
|
||||
(check-equiv? (term (reduce ,Δ (((((elim nat Type) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat)
|
||||
(s (s x)))))
|
||||
(s zero))))
|
||||
(term (s (s zero))))
|
||||
(check-equiv? (term (reduce ,Δ (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(check-equiv? (term (reduce ,Δ (((((elim nat Type) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
(s (s (s zero))))))
|
||||
(term (s (s (s (s zero))))))
|
||||
|
||||
(check-equiv?
|
||||
(term (reduce ,Δ
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s (s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s (s zero)))))
|
||||
(((((elim nat Type) (λ (x : nat) nat))
|
||||
(s (s zero)))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s (s zero)))))
|
||||
(term (s (s (s (s zero))))))
|
||||
(check-equiv?
|
||||
(term (step ,Δ
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s (s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s (s zero)))))
|
||||
(((((elim nat Type) (λ (x : nat) nat))
|
||||
(s (s zero)))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s (s zero)))))
|
||||
(term
|
||||
(((λ (x : nat) (λ (ih-x : nat) (s ih-x)))
|
||||
(s zero))
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s (s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s zero)))))
|
||||
(((((elim nat Type) (λ (x : nat) nat))
|
||||
(s (s zero)))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s zero)))))
|
||||
(check-equiv?
|
||||
(term (step ,Δ (step ,Δ
|
||||
(((λ (x : nat) (λ (ih-x : nat) (s ih-x)))
|
||||
(s zero))
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s (s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s zero))))))
|
||||
(((((elim nat Type) (λ (x : nat) nat))
|
||||
(s (s zero)))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
(s zero))))))
|
||||
(term
|
||||
((λ (ih-x1 : nat) (s ih-x1))
|
||||
(((λ (x : nat) (λ (ih-x : nat) (s ih-x)))
|
||||
zero)
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s (s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
zero)))))
|
||||
(((((elim nat Type) (λ (x : nat) nat))
|
||||
(s (s zero)))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s ih-x))))
|
||||
zero)))))
|
||||
|
||||
(define-syntax-rule (check-equivalent e1 e2)
|
||||
(check-holds (convert ∅ ∅ e1 e2)))
|
||||
(check-holds (equivalent ∅ e1 e2)))
|
||||
(check-equivalent
|
||||
(λ (x : Type) x) (λ (y : Type) y))
|
||||
(check-equivalent
|
||||
|
@ -316,42 +343,28 @@
|
|||
U))
|
||||
;; ---- Elim
|
||||
;; TODO: Clean up/Reorganize these tests
|
||||
(check-true
|
||||
(redex-match? tt-typingL
|
||||
(in-hole Θ_m (((elim x_D U) e_D) e_P))
|
||||
(term ((((elim truth Type) T) (Π (x : truth) (Unv 1))) (Unv 0)))))
|
||||
(define Δtruth (term (∅ (truth : (Unv 0) ((T : truth))))))
|
||||
(check-holds (type-infer ,Δtruth ∅ truth (in-hole Ξ U)))
|
||||
(check-holds (type-infer ,Δtruth ∅ T (in-hole Θ_ai truth)))
|
||||
(check-holds (type-infer ,Δtruth ∅ (λ (x : truth) (Unv 1))
|
||||
(in-hole Ξ (Π (x : (in-hole Θ truth)) U))))
|
||||
|
||||
(check-equiv?
|
||||
(term (Δ-motive-type ,Δtruth truth (Unv 2)))
|
||||
(term (Π (x : truth) (Unv 2))))
|
||||
|
||||
|
||||
(check-holds (type-check ,Δtruth ∅ (Unv 0) ,(car (term (Δ-method-types ,Δtruth truth (λ (x : truth) (Unv 1)))))))
|
||||
|
||||
(check-holds (type-check ,Δtruth ∅ (λ (x : truth) (Unv 1)) (Π (x : truth) (Unv 2))))
|
||||
|
||||
(check-equiv?
|
||||
(term (apply (λ (x : truth) (Unv 1)) T))
|
||||
(term ((λ (x : truth) (Unv 1)) T)))
|
||||
|
||||
(check-holds
|
||||
(convert ,Δtruth ∅ (apply (λ (x : truth) (Unv 1)) T) (Unv 1)))
|
||||
|
||||
(check-holds (type-infer ,Δtruth
|
||||
(check-telescope-equiv?
|
||||
(term (Δ-methods-telescope ,Δtruth truth (λ (x : truth) (Unv 1))))
|
||||
(term (Π (m-T : ((λ (x : truth) (Unv 1)) T)) hole)))
|
||||
(check-holds (type-infer ,Δtruth ∅ (elim truth Type) t))
|
||||
(check-holds (type-check (∅ (truth : (Unv 0) ((T : truth))))
|
||||
∅
|
||||
(elim truth (λ (x : truth) (Unv 1))
|
||||
() ((Unv 0)) T)
|
||||
t))
|
||||
|
||||
(check-holds (type-check ,Δtruth
|
||||
∅
|
||||
(elim truth (λ (x : truth) (Unv 1))
|
||||
() ((Unv 0)) T)
|
||||
((((elim truth (Unv 2)) (λ (x : truth) (Unv 1))) (Unv 0))
|
||||
T)
|
||||
(Unv 1)))
|
||||
(check-not-holds (type-check (∅ (truth : (Unv 0) ((T : truth))))
|
||||
∅
|
||||
(elim truth Type () (Type) T)
|
||||
((((elim truth (Unv 1)) Type) Type) T)
|
||||
(Unv 1)))
|
||||
(check-holds
|
||||
(type-infer ∅ ∅ (Π (x2 : (Unv 0)) (Unv 0)) U))
|
||||
|
@ -369,54 +382,47 @@
|
|||
(check-holds (type-check ,Δ syn ...)))
|
||||
(nat-test ∅ (Π (x : nat) nat) (Unv 0))
|
||||
(nat-test ∅ (λ (x : nat) x) (Π (x : nat) nat))
|
||||
(nat-test ∅ (elim nat (λ (x : nat) nat) ()
|
||||
(zero (λ (x : nat) (λ (ih-x : nat) x)))
|
||||
zero)
|
||||
(nat-test ∅ (((((elim nat Type) (λ (x : nat) nat)) zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) x))) zero)
|
||||
nat)
|
||||
(nat-test ∅ nat (Unv 0))
|
||||
(nat-test ∅ zero nat)
|
||||
(nat-test ∅ s (Π (x : nat) nat))
|
||||
(nat-test ∅ (s zero) nat)
|
||||
;; TODO: Meta-function auto-currying and such
|
||||
(check-holds
|
||||
(type-infer ,Δ ∅ (λ (x : nat)
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
(zero
|
||||
(λ (x : nat) (λ (ih-x : nat) x)))
|
||||
x))
|
||||
(type-infer ,Δ ∅ ((((elim nat (Unv 0)) (λ (x : nat) nat))
|
||||
zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) x)))
|
||||
t))
|
||||
(nat-test ∅ (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
(zero (λ (x : nat) (λ (ih-x : nat) x)))
|
||||
zero)
|
||||
(nat-test ∅ (((((elim nat (Unv 0)) (λ (x : nat) nat))
|
||||
zero)
|
||||
(λ (x : nat) (λ (ih-x : nat) x)))
|
||||
zero)
|
||||
nat)
|
||||
(nat-test ∅ (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s zero) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
zero)
|
||||
(nat-test ∅ (((((elim nat (Unv 0)) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
zero)
|
||||
nat)
|
||||
(nat-test ∅ (elim nat (λ (x : nat) nat)
|
||||
()
|
||||
((s zero) (λ (x : nat) (λ (ih-x : nat) (s (s x)))))
|
||||
zero)
|
||||
(nat-test ∅ (((((elim nat Type) (λ (x : nat) nat))
|
||||
(s zero))
|
||||
(λ (x : nat) (λ (ih-x : nat) (s (s x))))) zero)
|
||||
nat)
|
||||
(nat-test (∅ n : nat)
|
||||
(elim nat (λ (x : nat) nat)
|
||||
()
|
||||
(zero (λ (x : nat) (λ (ih-x : nat) x)))
|
||||
n)
|
||||
(((((elim nat (Unv 0)) (λ (x : nat) nat)) zero) (λ (x : nat) (λ (ih-x : nat) x))) n)
|
||||
nat)
|
||||
(check-holds
|
||||
(type-check (,Δ (bool : (Unv 0) ((btrue : bool) (bfalse : bool))))
|
||||
(∅ n2 : nat)
|
||||
(elim nat (λ (x : nat) bool)
|
||||
()
|
||||
(btrue (λ (x : nat) (λ (ih-x : bool) bfalse)))
|
||||
n2)
|
||||
(((((elim nat (Unv 0)) (λ (x : nat) bool))
|
||||
btrue)
|
||||
(λ (x : nat) (λ (ih-x : bool) bfalse)))
|
||||
n2)
|
||||
bool))
|
||||
(check-not-holds
|
||||
(type-check ,Δ ∅
|
||||
(elim nat nat () ((s zero)) zero)
|
||||
((((elim nat (Unv 0)) nat) (s zero)) zero)
|
||||
nat))
|
||||
(define lam (term (λ (nat : (Unv 0)) nat)))
|
||||
(check-equivalent
|
||||
|
@ -475,15 +481,15 @@
|
|||
(in-hole Ξ (Π (x : (in-hole Θ_Ξ and)) U_P))))
|
||||
(check-holds
|
||||
(type-check (,Δ4 (true : (Unv 0) ((tt : true)))) ∅
|
||||
(elim and
|
||||
(λ (A : Type) (λ (B : Type) (λ (x : ((and A) B))
|
||||
true)))
|
||||
(true true)
|
||||
((λ (A : (Unv 0))
|
||||
(λ (B : (Unv 0))
|
||||
(λ (a : A)
|
||||
(λ (b : B) tt)))))
|
||||
((((conj true) true) tt) tt))
|
||||
((((((elim and (Unv 0))
|
||||
(λ (A : Type) (λ (B : Type) (λ (x : ((and A) B))
|
||||
true))))
|
||||
(λ (A : (Unv 0))
|
||||
(λ (B : (Unv 0))
|
||||
(λ (a : A)
|
||||
(λ (b : B) tt)))))
|
||||
true) true)
|
||||
((((conj true) true) tt) tt))
|
||||
true))
|
||||
(check-true (Γ? (term (((∅ P : (Unv 0)) Q : (Unv 0)) ab : ((and P) Q)))))
|
||||
(check-holds
|
||||
|
@ -501,7 +507,7 @@
|
|||
((and B) A))))
|
||||
(in-hole Ξ (Π (x : (in-hole Θ and)) U))))
|
||||
(check-holds
|
||||
(convert ,Δ4 ∅
|
||||
(equivalent ,Δ4
|
||||
(Π (A : (Unv 0)) (Π (B : (Unv 0)) (Π (x : ((and A) B)) (Unv 0))))
|
||||
(Π (P : (Unv 0)) (Π (Q : (Unv 0)) (Π (x : ((and P) Q)) (Unv 0))))))
|
||||
(check-holds
|
||||
|
@ -512,15 +518,14 @@
|
|||
(check-holds
|
||||
(type-check ,Δ4
|
||||
(((∅ P : (Unv 0)) Q : (Unv 0)) ab : ((and P) Q))
|
||||
(elim and
|
||||
(λ (A : Type) (λ (B : Type) (λ (x : ((and A) B))
|
||||
((and B) A))))
|
||||
(P Q)
|
||||
((λ (A : (Unv 0))
|
||||
(λ (B : (Unv 0))
|
||||
(λ (a : A)
|
||||
(λ (b : B) ((((conj B) A) b) a))))))
|
||||
ab)
|
||||
((((((elim and (Unv 0))
|
||||
(λ (A : Type) (λ (B : Type) (λ (x : ((and A) B))
|
||||
((and B) A)))))
|
||||
(λ (A : (Unv 0))
|
||||
(λ (B : (Unv 0))
|
||||
(λ (a : A)
|
||||
(λ (b : B) ((((conj B) A) b) a))))))
|
||||
P) Q) ab)
|
||||
((and Q) P)))
|
||||
(check-holds
|
||||
(type-check (,Δ4 (true : (Unv 0) ((tt : true)))) ∅
|
||||
|
@ -533,14 +538,14 @@
|
|||
t))
|
||||
(check-holds
|
||||
(type-check (,Δ4 (true : (Unv 0) ((tt : true)))) ∅
|
||||
(elim and
|
||||
((((((elim and (Unv 0))
|
||||
(λ (A : Type) (λ (B : Type) (λ (x : ((and A) B))
|
||||
((and B) A))))
|
||||
(true true)
|
||||
((λ (A : (Unv 0))
|
||||
((and B) A)))))
|
||||
(λ (A : (Unv 0))
|
||||
(λ (B : (Unv 0))
|
||||
(λ (a : A)
|
||||
(λ (b : B) ((((conj B) A) b) a))))))
|
||||
true) true)
|
||||
((((conj true) true) tt) tt))
|
||||
((and true) true)))
|
||||
(define gamma (term (∅ temp863 : pre)))
|
||||
|
@ -563,18 +568,21 @@
|
|||
(check-holds
|
||||
(type-infer ,sigma (,gamma x : false) (λ (y : false) (Π (x : Type) x))
|
||||
(in-hole Ξ (Π (x : (in-hole Θ false)) U))))
|
||||
|
||||
(check-true
|
||||
(redex-match? tt-typingL
|
||||
((in-hole Θ_m ((elim x_D U) e_P)) e_D)
|
||||
(term (((elim false (Unv 1)) (λ (y : false) (Π (x : Type) x)))
|
||||
x))))
|
||||
(check-holds
|
||||
(type-check ,sigma (,gamma x : false)
|
||||
(elim false (λ (y : false) (Π (x : Type) x)) () () x)
|
||||
(((elim false (Unv 0)) (λ (y : false) (Π (x : Type) x))) x)
|
||||
(Π (x : (Unv 0)) x)))
|
||||
|
||||
;; nat-equal? tests
|
||||
(define zero?
|
||||
(term (λ (n : nat)
|
||||
(elim nat (λ (x : nat) bool) ()
|
||||
(true (λ (x : nat) (λ (x_ih : bool) false)))
|
||||
n))))
|
||||
(term ((((elim nat Type) (λ (x : nat) bool))
|
||||
true)
|
||||
(λ (x : nat) (λ (x_ih : bool) false)))))
|
||||
(check-holds
|
||||
(type-check ,Δ ∅ ,zero? (Π (x : nat) bool)))
|
||||
(check-equal?
|
||||
|
@ -584,12 +592,9 @@
|
|||
(term (reduce ,Δ (,zero? (s zero))))
|
||||
(term false))
|
||||
(define ih-equal?
|
||||
(term (λ (ih : nat)
|
||||
(elim nat (λ (x : nat) bool)
|
||||
()
|
||||
(false
|
||||
(λ (x : nat) (λ (y : bool) (x_ih x))))
|
||||
ih))))
|
||||
(term ((((elim nat Type) (λ (x : nat) bool))
|
||||
false)
|
||||
(λ (x : nat) (λ (y : bool) (x_ih x))))))
|
||||
(check-holds
|
||||
(type-check ,Δ (∅ x_ih : (Π (x : nat) bool))
|
||||
,ih-equal?
|
||||
|
@ -601,13 +606,10 @@
|
|||
(check-holds
|
||||
(type-infer ,Δ ∅ (λ (x : nat) (Π (x : nat) bool)) (Π (x : nat) (Unv 0))))
|
||||
(define nat-equal?
|
||||
(term (λ (n : nat)
|
||||
(elim nat (λ (x : nat) (Π (x : nat) bool))
|
||||
()
|
||||
(,zero?
|
||||
(λ (x : nat) (λ (x_ih : (Π (x : nat) bool))
|
||||
,ih-equal?)))
|
||||
n))))
|
||||
(term ((((elim nat Type) (λ (x : nat) (Π (x : nat) bool)))
|
||||
,zero?)
|
||||
(λ (x : nat) (λ (x_ih : (Π (x : nat) bool))
|
||||
,ih-equal?)))))
|
||||
(check-holds
|
||||
(type-check ,Δ (∅ nat-equal? : (Π (x-D«4158» : nat) ((λ (x«4159» : nat) (Π (x«4160» : nat) bool)) x-D«4158»)))
|
||||
((nat-equal? zero) zero)
|
||||
|
@ -629,12 +631,19 @@
|
|||
(check-true (Δ? Δ=))
|
||||
|
||||
(define refl-elim
|
||||
(term (elim == (λ (A1 : (Unv 0)) (λ (x1 : A1) (λ (y1 : A1) (λ (p2 : (((== A1) x1) y1)) nat))))
|
||||
(bool true true)
|
||||
((λ (A1 : (Unv 0)) (λ (x1 : A1) zero)))
|
||||
((refl bool) true))))
|
||||
(term (((((((elim == (Unv 0)) (λ (A1 : (Unv 0)) (λ (x1 : A1) (λ (y1 : A1) (λ (p2 : (((==
|
||||
A1)
|
||||
x1)
|
||||
y1))
|
||||
nat)))))
|
||||
(λ (A1 : (Unv 0)) (λ (x1 : A1) zero))) bool) true) true) ((refl bool) true))))
|
||||
(check-holds
|
||||
(type-check ,Δ= ∅ ,refl-elim nat))
|
||||
(check-true
|
||||
(redex-match?
|
||||
tt-redL
|
||||
(Δ (in-hole E (in-hole Θ ((elim x_D U) e_P))))
|
||||
(term (,Δ= ,refl-elim))))
|
||||
(check-true
|
||||
(redex-match?
|
||||
tt-redL
|
||||
|
|
|
@ -32,11 +32,11 @@
|
|||
(:: (lambda (A : Type) (n : Nat) (none A)) (forall (A : Type) (-> Nat (Maybe A)))))
|
||||
(check-equal?
|
||||
(void)
|
||||
(:: (elim List (lambda (A : Type) (ls : (List A)) Nat)
|
||||
(Bool)
|
||||
((lambda (A : Type) z)
|
||||
(lambda (A : Type) (a : A) (ls : (List A)) (ih : Nat)
|
||||
z))
|
||||
(:: (elim List Type (lambda (A : Type) (ls : (List A)) Nat)
|
||||
(lambda (A : Type) z)
|
||||
(lambda (A : Type) (a : A) (ls : (List A)) (ih : Nat)
|
||||
z)
|
||||
Bool
|
||||
(nil Bool))
|
||||
Nat))
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
(:: pf:proj1 thm:proj1)
|
||||
(:: pf:proj2 thm:proj2)
|
||||
(check-equal?
|
||||
(elim == (λ (A : Type) (x : A) (y : A) (p : (== A x y)) Nat)
|
||||
(Bool
|
||||
true
|
||||
true)
|
||||
((λ (A : Type) (x : A) z))
|
||||
(elim == Type (λ (A : Type) (x : A) (y : A) (p : (== A x y)) Nat)
|
||||
(λ (A : Type) (x : A) z)
|
||||
Bool
|
||||
true
|
||||
true
|
||||
(refl Bool true))
|
||||
z)
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
(equal? : (forall (a : A) (b : A) Bool)))
|
||||
(impl (Eqv Bool)
|
||||
(define (equal? (a : Bool) (b : Bool))
|
||||
(if a b (not b))))
|
||||
(if a
|
||||
(if b true false)
|
||||
(if b false true))))
|
||||
(impl (Eqv Nat)
|
||||
(define equal? nat-equal?))
|
||||
(check-equal?
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
#lang sweet-exp cur
|
||||
require
|
||||
cur/stdlib/sugar
|
||||
cur/stdlib/bool
|
||||
cur/stdlib/nat
|
||||
rackunit
|
||||
|
||||
check-equal?
|
||||
if true false true
|
||||
false
|
||||
|
||||
define + plus
|
||||
|
||||
check-equal?
|
||||
{z + s(z)}
|
||||
s(z)
|
|
@ -1,7 +1,7 @@
|
|||
#lang info
|
||||
(define collection 'multi)
|
||||
(define deps '())
|
||||
(define build-deps '("base" "rackunit-lib" ("cur-lib" #:version "0.4") "sweet-exp"))
|
||||
(define build-deps '("base" "rackunit-lib" ("cur-lib" #:version "0.2")))
|
||||
(define update-implies '("cur-lib"))
|
||||
(define pkg-desc "Tests for \"cur\".")
|
||||
(define pkg-authors '(wilbowma))
|
||||
|
|
Loading…
Reference in New Issue
Block a user