#lang racket (require redex "list-machine.rkt") (provide list-machine-typing check-program check-blocks check-block check-instr :set :lookup ⊂ ⊔ Γ-⊂ dom l-⊂) (define-extended-language list-machine-typing list-machine (τ nil (list τ) (listcons τ)) (Γ empty (v : τ Γ)) (Π empty (l : Γ Π))) (define-judgment-form list-machine-typing #:contract (check-program p Π) #:mode (check-program I I) [(check-blocks Π p) (where #t (l-⊂ (dom Π) (dom p))) (:lookup Π l0 (v0 : nil empty)) ----- (check-program p Π)]) (define-judgment-form list-machine-typing #:contract (Γ-⊂ Γ Γ) #:mode (Γ-⊂ I I) [----- (Γ-⊂ Γ empty)] [(:lookup Γ_1 v τ_1) (⊂ τ_1 τ_2) (Γ-⊂ Γ_1 Γ_2) ---- (Γ-⊂ Γ_1 (v : τ_2 Γ_2))]) (define-judgment-form list-machine-typing #:contract (check-blocks Π p) #:mode (check-blocks I I) [(:lookup Π l Γ) (check-block Π Γ ι) (check-blocks Π p) ----- (check-blocks Π (l : ι p)) ] [----- (check-blocks Π end)]) (define-judgment-form list-machine-typing #:contract (check-block Π Γ ι) #:mode (check-block I I I) [----- (check-block Π Γ halt)] [(check-instr Π Γ ι_1 Γ_2) (check-block Π Γ_2 ι_2) ----- (check-block Π Γ (begin ι_1 ι_2))] [(:lookup Π l Γ_2) (Γ-⊂ Γ Γ_2) ----- (check-block Π Γ (jump l))]) (define-judgment-form list-machine-typing #:contract (check-instr Π Γ ι Γ) #:mode (check-instr I I I O) [(check-instr Π Γ ι_1 Γ_1) (check-instr Π Γ_1 ι_2 Γ_2) ----- (check-instr Π Γ (begin ι_1 ι_2) Γ_2)] [(:lookup Γ v (list τ)) (:lookup Π l Γ_1) (:set Γ v nil Γ_3) (Γ-⊂ Γ_3 Γ_1) (:set Γ_3 v (listcons τ) Γ_2) ----- (check-instr Π Γ (branch-if-nil v l) Γ_2)] [(:lookup Γ v (listcons τ)) (:lookup Π l Γ_1) (:set Γ v nil Γ_2) (Γ-⊂ Γ_2 Γ_1) ----- (check-instr Π Γ (branch-if-nil v l) Γ)] [(:lookup Γ v nil) (:lookup Π l Γ_1) (Γ-⊂ Γ Γ_1) ----- (check-instr Π Γ (branch-if-nil v l) Γ)] [(:lookup Γ v (listcons τ)) (:set Γ v_2 τ Γ_2) ----- (check-instr Π Γ (fetch-field v 0 v_2) Γ_2)] [(:lookup Γ v (listcons τ)) (:set Γ v_2 (list τ) Γ_2) ----- (check-instr Π Γ (fetch-field v 1 v_2) Γ_2)] [(:lookup Γ v_0 τ_0) (:lookup Γ v_0 τ_1) (⊔ (list τ_0) τ_1 (list τ)) (:set Γ v (listcons τ) Γ_2) ----- (check-instr Π Γ (cons v_0 v_1 v) Γ_2)]) (define-judgment-form list-machine-typing #:contract (⊂ τ τ) #:mode (⊂ O I) [----- (⊂ τ τ)] [----- (⊂ nil (list τ))] [(⊂ τ τ_2) ----- (⊂ (list τ) (list τ_2))] [(⊂ τ τ_2) ----- (⊂ (listcons τ) (list τ_2))] [(⊂ τ τ_2) ----- (⊂ (listcons τ) (listcons τ_2))]) (define-judgment-form list-machine-typing #:contract (⊔ τ τ τ) #:mode (⊔ I I O) [----- (⊔ τ τ τ)] [----- (⊔ (list τ) nil (list τ))] [----- (⊔ nil (list τ) (list τ))] [(⊔ (list τ_1) (list τ_2) τ_3) ----- (⊔ (list τ_1) (listcons τ_2) τ_3)] [(⊔ (list τ_1) (list τ_2) τ_3) ----- (⊔ (listcons τ_1) (list τ_2) τ_3)] [(⊔ τ_1 τ_2 τ_3) ----- (⊔ (list τ_1) (list τ_2) (list τ_3))] [----- (⊔ (listcons τ) nil (list τ))] [----- (⊔ nil (listcons τ) (list τ))] [(⊔ τ_1 τ_2 τ_3) ----- (⊔ (listcons τ_1) (listcons τ_2) (listcons τ_3))]) (define-judgment-form list-machine-typing #:contract (:lookup any v any) #:mode (:lookup I I O) [----- (:lookup (v : any_τ any_Γ) v any_τ)] [(where #t (different v_1 v_2)) (:lookup any_Γ v_2 any_τ2) ----- (:lookup (v_1 : any_τ1 any_Γ) v_2 any_τ2)]) (define-judgment-form list-machine-typing #:contract (:set Γ v τ Γ) #:mode (:set I I I O) [----- (:set (v : any_τ any_Γ) v any_τ2 (v : any_τ2 any_Γ))] [(where #t (different v v_2)) (:set any_Γ v_2 any_τ2 any_Γ2) ----- (:set (v : any_τ any_Γ) v_2 any_τ2 (v : any_τ any_Γ2))] [----- (:set empty v any_τ (v : any_τ empty))]) (define-metafunction list-machine-typing dom : any -> (l ...) [(dom (l_1 : any_1 any_2)) (l_1 l_2 ...) (where (l_2 ...) (dom any_2))] [(dom any) ()]) (define-metafunction list-machine-typing l-⊂ : (l ...) (l ...) -> any [(l-⊂ (l_1 ...) (l_2 ...)) ,(let ([ht (make-hash)]) (for ([l (in-list (term (l_2 ...)))]) (hash-set! ht l #t)) (for/and ([l (in-list (term (l_1 ...)))]) (hash-ref ht l #f)))])