#lang typed-scheme #;(require mzlib/etc) #;(require "prims.rkt") (require mzlib/match (for-syntax scheme/base)) (define-type-alias number Number) (define-type-alias boolean Boolean) (define-type-alias symbol Symbol) (define-type-alias top Any) (define-type-alias list-of Listof) (define-type-alias atom (Un Number Symbol Boolean)) (define: atom? : (Any -> Boolean : atom) (lambda: ([v : Any]) (if (number? v) #t (if (symbol? v) #t (boolean? v))))) (define-syntax (cond* stx) (syntax-case stx (else) [(_ [pred expr id rhs] . rest) (quasisyntax/loc stx (let ([id expr]) (if (pred id) rhs #,(syntax/loc #'rest (cond . rest)))))] [(_ [else . rest]) #'(begin . rest)] [(_ [p . rhs] . rest) #'(if p (begin . rhs) (cond* . rest))])) (define-type-alias lat (list-of atom)) (define: (lat? [l : (list-of top)]) : boolean (cond [(null? l) #t] [(atom? (car l)) (lat? (cdr l))] [else #f])) (define: (member? [a : atom] [l : lat]) : boolean (cond [(null? l) #f] [else (or (equal? a (car l)) (member? a (cdr l)))])) (define: (rember [a : symbol] [l : (list-of symbol)]) : (list-of symbol) (cond [(null? l) l] [(eq? (car l) a) (cdr l)] [else (cons (car l) (rember a (cdr l)))])) (define: (multisubst [new : symbol] [old : symbol] [lat : (list-of symbol)]) : (list-of symbol) (cond [(null? lat) lat] [(eq? (car lat) old) (cons new (multisubst new old (cdr lat)))] [else (cons (car lat) (multisubst new old (cdr lat)))])) (define: (tup+ [t1 : (list-of number)] [t2 : (list-of number)]) : (list-of number) (cond [(null? t1) t2] [(null? t2) t1] [else (cons (+ (car t1) (car t2)) (tup+ (cdr t1) (cdr t2)))])) (define: (len [l : (list-of top)]) : number (cond [(null? l) 0] [else (add1 (len (cdr l)))])) (define: (pick [n : number] [lat : (list-of symbol)]) : symbol (cond [(zero? (sub1 n)) (car lat)] [else (pick (sub1 n) (cdr lat))])) (define: (no-nums [lat : (list-of atom)]) : (list-of atom) (cond [(null? lat) lat] [(number? (car lat)) (no-nums (cdr lat))] [else (cons (car lat) (no-nums (cdr lat)))])) (define: (one? [n : number]) : boolean (= n 1)) (define: (rempick [n : number] [lat : (list-of atom)]) : (list-of atom) (cond [(one? n) (cdr lat)] [else (cons (car lat) (rempick (sub1 n) (cdr lat)))])) (define: (foo2 [x : top]) : boolean (if (number? x) (= x x) #f)) ;; doesn't work because of and! - bug in type system (define: (eqan? [a1 : top] [a2 : top]) : boolean (cond [(and (number? a1) (number? a2)) (= a1 a2)] [else (eq? a1 a2)])) (define: (occur [a : atom] [lat : (list-of atom)]) : number (cond [(null? lat) 0] [(eq? (car lat) a) (add1 (occur a (cdr lat)))] [else (occur a (cdr lat))])) (define-type-alias SExp (mu x (U atom (Listof x)))) ;; (atom? (car l)) doesn't do anything - bug in type system #;(define: (rember* [a : atom] [l : (list-of SExp)]) : (list-of SExp) (cond [(null? l) l] [(atom? (car l)) (cond [(eq? (car l) a) (rember* a (cdr l))] [else (cons (car l) (rember* a (cdr l)))])] [else (cons (rember* a (car l)) (rember* a (cdr l)))])) (define: (rember* [a : atom] [l : (list-of SExp)]) : (list-of SExp) (cond [(null? l) l] [else (let ([c (car l)]) (cond [(atom? c) (cond [(eq? c a) (rember* a (cdr l))] [else (cons c (rember* a (cdr l)))])] [else (cons (rember* a c) (rember* a (cdr l)))]))])) (define: (insertR* [new : atom] [old : atom] [l : (list-of SExp)]) : (list-of SExp) (cond [(null? l) l] [else (let ([c (car l)]) (cond [(atom? c) (cond [(eq? c old) (cons old (cons new (insertR* new old (cdr l))))] [else (cons c (insertR* new old (cdr l)))])] [else (cons (insertR* new old c) (insertR* new old (cdr l)))]))])) (define: (occur* [a : atom] [l : (list-of SExp)]) : number (cond* [(null? l) 0] [atom? (car l) c (cond [(eq? c a) (add1 (occur* a (cdr l)))] [else (occur* a (cdr l))])] [else (+ (occur* a c) (occur* a (cdr l)))])) (define: (member* [a : atom] [l : (list-of SExp)]) : boolean (cond* [(null? l) #f] [atom? (car l) c (or (eq? a c) (member* a (cdr l)))] [else (or (member* a c) (member* a (cdr l)))])) (define: (^ [n : number] [m : number]) : number (if (= m 0) 1 (* n (^ n (sub1 m))))) (define: (1st-sub-exp [ae : (list-of SExp)]) : SExp (car ae)) (define: (2nd-sub-exp [ae : (list-of SExp)]) : SExp (car (cdr (cdr ae)))) (define: (operator [ae : (list-of SExp)]) : SExp (car (cdr ae))) (define-type-alias num-exp (Rec N (U Number (List N (U '+ '* '^) N)))) (define: (value [nexp : num-exp]) : number (cond [(atom? nexp) nexp] [(eq? (car (cdr nexp)) '+) (+ (value (car nexp)) (value (car (cdr (cdr nexp)))))] [(eq? (car (cdr nexp)) '*) (* (value (car nexp)) (value (car (cdr (cdr nexp)))))] [else (^ (value (car nexp)) (value (car (cdr (cdr nexp)))))] )) #;(define-type aexp (Un atom (list-of aexp))) (define: (set? [l : (list-of atom)]) : boolean (cond [(null? l) #t] [(member? (car l) (cdr l)) #f] [else (set? (cdr l))])) (define: (multirember [a : atom] [l : (list-of atom)]) : (list-of atom) (cond [(null? l) l] [(equal? a (car l)) (multirember a (cdr l))] [else (cons (car l) (multirember a (cdr l)))])) (define: (makeset [l : lat]) : lat (cond [(null? l) l] [else (cons (car l) (makeset (multirember (car l) (cdr l))))])) (define: (subset? [set1 : lat] [set2 : lat]) : boolean (cond [(null? set1) #t] [(member? (car set1) set2) (subset? (cdr set1) set2)] [else #f])) (define: (subset2? [set1 : (list-of atom)] [set2 : (list-of atom)]) : boolean (cond [(null? set1) #t] [else (and (member? (car set1) set2) (subset? (cdr set1) set2))])) (define: (intersect? [set1 : (list-of atom)] [set2 : (list-of atom)]) : boolean (cond [(null? set1) #t] [else (or (member? (car set1) set2) (intersect? (cdr set1) set2))])) (define: (eqset? [set1 : (list-of atom)] [set2 : (list-of atom)]) : boolean (and (subset? set1 set2) (subset? set2 set1))) (define: (intersect [set1 : (list-of atom)] [set2 : (list-of atom)]) : (list-of atom) (cond [(null? set1) set1] [(member? (car set1) set2) (cons (car set1) (intersect (cdr set1) set2))] [else (intersect (cdr set1) set2)]) ) (define: (union [set1 : (list-of atom)] [set2 : (list-of atom)]) : (list-of atom) (cond [(null? set1) set2] [(member? (car set1) set2) (union (cdr set1) set2)] [else (cons (car set1) (intersect (cdr set1) set2))]) ) (define: (rember-f [test? : (atom atom -> boolean)] [a : atom] [l : (list-of atom)]) : (list-of atom) (cond [(null? l) l] [(test? (car l) a) (cdr l)] [else (cons (car l) (rember-f test? a (cdr l)))])) (define: (rember-f-curry [test? : (atom atom -> boolean)]) : (atom lat -> lat) (lambda: ([a : atom] [l : (list-of atom)]) (cond [(null? l) l] [(test? (car l) a) (cdr l)] [else (cons (car l) ((rember-f-curry test?) a (cdr l)))]))) (define: eq?-c : (atom -> (atom -> boolean)) (lambda: ([a : atom]) (lambda: ([x : atom]) (eq? x a)))) (define: (insertR-f [test? : (atom atom -> boolean)] [new : atom] [old : atom] [l : (list-of atom)]) : (list-of atom) (cond [(null? l) l] [(test? (car l) old) (cons old (cons new (cdr l)))] [else (cons (car l) (insertR-f test? new old (cdr l)))])) (define: (seqL [new : atom] [old : atom] [l : (list-of atom)]) : (list-of atom) (cons new (cons old l))) (define: (seqR [new : atom] [old : atom] [l : (list-of atom)]) : (list-of atom) (cons old (cons new l))) (define: (insertR-g [seq : (atom atom lat -> lat)] [test? : (atom atom -> boolean)] [new : atom] [old : atom] [l : (list-of atom)]) : (list-of atom) (cond [(null? l) l] [(test? (car l) old) (seq new old (cdr l))] [else (cons (car l) (insertR-g seq test? new old (cdr l)))])) (define: (insertR-g-curry [seq : (atom atom (list-of atom) -> (list-of atom))]) : ((atom atom -> boolean) atom atom (list-of atom) -> (list-of atom)) (lambda: ([test? : (atom atom -> boolean)] [new : atom] [old : atom] [l : (list-of atom)]) (cond [(null? l) l] [(test? (car l) old) (seq new old (cdr l))] [else (cons (car l) ((insertR-g-curry seq) test? new old (cdr l)))]))) (define: (seqS [new : atom] [old : atom] [l : lat]) : lat (cons new l)) #;(define: subst : ((atom atom -> boolean) atom atom (list-of atom) -> (list-of atom)) (insertR-g-curry seqS)) (define: (atom->function [x : atom]) : (number number -> number) (case x [(+) +] [(*) *] [else ^])) ;; doesn't work - is operator really a number? (bug in type system) ;; also infinite loops checking num-exp <: SExp #;(define: (value-new [nexp : num-exp]) : number (cond [(number? nexp) nexp] [else ((atom->function (operator nexp)) (value-new (1st-sub-exp nexp)) (value-new (2nd-sub-exp nexp)))])) (define: (multiremberT [test? : (atom -> boolean)] [l : (list-of atom)]) : (list-of atom) (cond [(null? l) l] [(test? (car l)) (multiremberT test? (cdr l))] [else (cons (car l) (multiremberT test? (cdr l)))])) (define: (build [a : SExp] [b : SExp]) : (list-of SExp) (cons a (cons b '()))) (define: (first [pair : (list-of SExp)]) : SExp (car pair)) (define: (second [pair : (list-of SExp)]) : SExp (car (cdr pair))) ;; need to specify more about the list in the type here - type system bug #;(define: (shift [pair : (list-of SExp)]) : (list-of SExp) (build (first (first pair)) (build (second (first pair)) (second pair)))) ;; changed to test for exact-integer? before even? check. (define: (collatz [n : number]) : number (cond [(one? n) 1] [(and (exact-integer? n) (even? n)) (collatz (/ n 2))] [else (collatz (add1 (* 3 n)))])) (define: (ack [n : number] [m : number]) : number (cond [(zero? n) (add1 m)] [(zero? m) (ack (sub1 n) 1)] [else (ack (sub1 n) (ack n (sub1 m)))])) ;(define-type-alias entry (list-of (list-of atom))) (define: empty-atom : (list-of (list-of atom)) '()) ;; FIXME (define: mymap : (All (a b) ((a -> b) (list-of a) -> (list-of b))) (plambda: (a b) ([f : (a -> b)] [l : (list-of a)]) (cond [(null? l) '()] [else (cons (f (car l)) (mymap f (cdr l)))]))) (mymap add1 (cons 1 (cons 2 (cons 3 '())))) (define-type-alias entry (list-of lat)) (define-type-alias table (list-of entry)) (define: (new-entry [keys : (list-of atom)] [vals : (list-of atom)]) : entry (cons keys (cons vals empty-atom))) (define: (numbered? [aexp : num-exp]) : boolean (cond [(number? aexp) #t] [(atom? aexp) #f] [else (and (numbered? (car aexp)) (numbered? (car (cdr (cdr aexp)))))])) (define: (lookup-in-entry-help [name : atom] [names : (list-of atom)] [values : (list-of atom)] [entry-f : (atom -> atom)]) : atom (cond [(null? names) (entry-f name)] [(eq? (car names) name) (car values)] [else (lookup-in-entry-help name (cdr names) (cdr values) entry-f)])) (define: (lookup-in-entry [name : atom] [e : entry] [fail : (atom -> atom)]) : atom (lookup-in-entry-help name (car e) (car (cdr e)) fail)) (define: extend-table : (entry table -> table) #{cons @ entry Any}) (define: (lookup-in-table [name : atom] [t : table] [fail : (atom -> atom)]) : atom (cond [(null? t) (fail name)] [else (lookup-in-entry name (car t) (lambda: ([name : atom]) (lookup-in-table name (cdr t) fail)))])) (define-type-alias action (atom table -> SExp)) (define: (*const [e : SExp] [t : table]) : SExp (cond [(number? e) e] [(eq? e #t) #t] [(eq? e #f) #f] [else (build 'primitive e)])) (define: (initial-table [name : atom]) : atom (error 'fail)) (define: (*identifier [e : atom] [tbl : table]) : SExp (lookup-in-table e tbl initial-table)) (define: (atom->action [e : atom]) : action (cond [(number? e) *const] #;[(string? e) (error "shouldn't get strings")] ;; FIXME - had to change the code [else (case e [(#t #f cons car cdr null? eq? atom? zero? add1 sub1 number?) *const] [else *identifier])])) (define: (*quote [a : atom] [t : table]) : SExp (error 'fail)) (define: (*lambda [a : atom] [t : table]) : SExp (error 'fail)) (define: (*cond [a : atom] [t : table]) : SExp (error 'fail)) (define: (*application [a : atom] [t : table]) : SExp (error 'fail)) (define: (list->action [e : (list-of SExp)]) : action (cond* [atom? (car e) it (case it [(quote) *quote] [(lambda) *lambda] [(cond) *cond] [else *application])] [else *application])) (define: (expression->action [e : SExp]) : action (cond [(atom? e) (atom->action e)] [else (list->action e)])) #;(define: (meaning [e : SExp] [t : table]) : SExp ((expression->action e) e t)) #;(define: (value [e : SExp]) : SExp (meaning e '())) #;(provide (all-defined))