#lang racket
(require
(prefix-in srfi: srfi/1)
"../constants.rkt"
"../nil-macros.rkt"
"../equality.rkt"
"../defun.rkt"
"../do-check.rkt"
(for-syntax syntax/parse))
(provide define/c)
(define-syntax (define/c stx)
(syntax-parse stx
#:literals [rename-out case-lambda]
[(_ f:id c:expr e:expr)
#'(begin
(define f
(let ()
(with-contract |Dracula Program|
([contracted any/c])
(define/contract f c e)
(define contracted f))
contracted))
(define-syntax macro
(lambda (stx*)
(syntax-parse stx*
[(_ . xs) #'(f . xs)]
[_ (raise-syntax-error 'f
"functions must appear in operator position" stx*)])))
(provide (rename-out [macro f])))]
[(_ ((rename-out [internal:id external:id]) . xs) c:expr e:expr)
#'(begin
(begin-below (defun macro xs (to-export . xs)))
(define (internal . xs) e)
(define to-export
(let ()
(with-contract |Dracula Program|
([contracted any/c])
(define/contract external c internal)
(define contracted external))
contracted))
(provide (rename-out [macro external])))]
[(_ (f:id . xs) c:expr e:expr)
#'(begin
(begin-below (defun macro xs (f . xs)))
(define f
(let ()
(with-contract |Dracula Program|
([contracted any/c])
(define/contract (f . xs) c e)
(define contracted f))
contracted))
(provide (rename-out [macro f])))]))
(define-syntax bool->CL
(syntax-rules ()
[(_ x) (if x t nil)]))
(define real/rational? rational?)
(define (acl2-symbol? x) (or (symbol? x) (null? x)))
(define symbolp/c (flat-named-contract "symbolp" acl2-symbol?))
(define nil/c (flat-named-contract "nil" null?))
(define (acl2-number? x) (number? x))
(define acl2-number/c (flat-named-contract "acl2-numberp" acl2-number?))
(define (non-zero-acl2-number? x) (and (acl2-number? x) (not (zero? x))))
(define (non-zero-real/rational? x) (and (real/rational? x) (not (zero? x))))
(define (eqlable? x)
(or (acl2-number? x) (acl2-symbol? x) (char? x)))
(define/c (eqlablep x) (any/c . -> . any) (bool->CL (eqlable? x)))
(define eqlablep/c (flat-named-contract "eqlablep" eqlable?))
(define/c (intern$ name package)
(-> string? string? symbol?)
(match package
["ACL2" (string->symbol name)]
["KEYWORD" (string->symbol (string-append ":" name))]
[_ (error 'intern$ "only packages ACL2 and KEYWORD are supported")]))
(define/c (intern-in-package-of-symbol name other)
(-> string? (or/c symbol? null?) symbol?)
(match other
[(app symbol->string (regexp #rx"^:"))
(string->symbol (string-append ":" name))]
[_ (string->symbol name)]))
(define-syntax (intern stx)
(syntax-case stx ()
[(_ name "ACL2") (syntax (intern$ name "ACL2"))]
[(_ name "KEYWORD") (syntax (intern$ name "KEYWORD"))]
[(_ name package)
(raise-syntax-error #f
"only packages ACL2 and KEYWORD are supported"
stx #'package)]
[_
(raise-syntax-error #f
"expected two arguments"
stx)]))
(provide intern)
(define/c (eq x y)
(([x any/c] [y (if (acl2-symbol? x) any/c symbolp/c)]) () . ->d . any)
(bool->CL (acl2-equal? x y)))
(define/c (eql x y)
(([x any/c] [y (if (eqlable? x) any/c eqlablep/c)]) () . ->d . any)
(bool->CL (acl2-equal? x y)))
(define/c (equal x y)
(any/c any/c . -> . any)
(bool->CL (acl2-equal? x y)))
(define-syntax (acl2:* stx)
(syntax-case stx (acl2:*)
[(_ . args) #'(* . args)]
[acl2:* (raise-syntax-error #f "Functions are allowed only in operator position" stx)]))
(provide (rename-out [acl2:* *]))
(define-syntax (acl2:+ stx)
(syntax-case stx (acl2:+)
[(_ . args) #'(+ . args)]
[acl2:+ (raise-syntax-error #f "Functions are allowed only in operator position" stx)]))
(provide (rename-out [acl2:+ +]))
(define acl2:-
(case-lambda
[(x) (- x)]
[(x y) (- x y)]
))
(define-syntax (macro- stx)
(syntax-case stx ()
[(_ x) #'(acl2:- x)]
[(_ x y) #'(acl2:- x y)]
[(_ . xs) (raise-syntax-error #f
(format "Expects only one or two arguments, but given ~a"
(length (syntax->list #'xs)))
stx)]
[_else (raise-syntax-error
#f "Functions are allowed only in operator position" stx)]))
(provide (rename-out [macro- -]))
(provide not-nil)
(define/c (symbolp x) (any/c . -> . any)
(bool->CL (or (symbol? x) (null? x))))
(define-syntax (a:list stx)
(syntax-case stx (a:list)
[(_ . xs) #'(list . xs)]
[a:list (raise-syntax-error #f
"Functions can only be used in operator position" stx)]))
(define-syntax (a:list* stx)
(syntax-case stx (a:list*)
[(_ . xs) #'(list* . xs)]
[a:list* (raise-syntax-error #f
"Functions can only be used in operator position" stx)]))
(provide (rename-out [a:list list] [a:list* list*]))
(define/c ((rename-out [a:cons cons]) x y) [any/c any/c . -> . any] (cons x y))
(define/c make-list
(case-> [natural-number/c . -> . any]
[natural-number/c (symbols ':initial-element) any/c . -> . any])
(case-lambda
[(size) (srfi:make-list size nil)]
[(size :initial-element fill) (srfi:make-list size fill)]))
(define/c (endp x) ((or/c nil/c pair?) . -> . any) (eq x nil))
(define/c ((rename-out [a:null null]) x) (any/c . -> . any) (eq x nil))
(define/c (consp x) (any/c . -> . any) (bool->CL (pair? x)))
(define (true-list? x) (or (nil? x)
(and (pair? x) (true-list? (cdr x)))))
(define/c (true-listp x)
(any/c . -> . any)
(bool->CL (true-list? x)))
(define/c ((rename-out [a:car car]) x) [(or/c nil/c (cons/c any/c any/c)) . -> . any]
(if (pair? x) (car x) '()))
(define/c ((rename-out [a:cdr cdr]) x) [(or/c nil/c (cons/c any/c any/c)) . -> . any]
(if (pair? x) (cdr x) '()))
(define/c (len x) (any/c . -> . any)
(let loop ([x x] [answer 0])
(if (pair? x) (loop (cdr x) (add1 answer)) answer)))
(define-syntax (acl2:append stx)
(syntax-case stx (acl2:append)
[(_ . xs) #'(append . xs)]
[acl2:append (raise-syntax-error #f "Functions are only allowed on operator position" stx)]))
(provide (rename-out [acl2:append append]))
(define/c concatenate (case-> [(symbols 'string 'list) . -> . any]
[(symbols 'string 'list)
#:rest (or/c (listof string?) (listof (listof any/c)))
. -> .
any])
(case-lambda
[(result-type) (if (eq? result-type 'list) '() "")]
[(result-type . args)
(apply (if (eq? result-type 'list) append string-append) args)]))
(define/c (revappend lst acc) [(listof any/c) any/c . -> . any]
(if (null? lst)
acc
(revappend (cdr lst) (cons (car lst) acc))))
(define/c ((rename-out [acl2-reverse reverse]) lst-or-str)
[(or/c string? (listof any/c)) . -> . any]
(if (string? lst-or-str)
(list->string (revappend (string->list lst-or-str) '()))
(revappend lst-or-str '())))
(define/c (intersectp-eq x y)
((listof acl2-symbol?) (listof acl2-symbol?) . -> . any)
(cond [(nil? x) nil]
[(memq (car x) y) t]
[else (intersectp-eq (cdr x) y)]))
(define/c (intersectp-equal x y)
((listof any/c) (listof any/c) . -> . any)
(cond [(nil? x) nil]
[(member (car x) y) t]
[else (intersectp-equal (cdr x) y)]))
(define/c (lognot x)
[integer? . -> . any]
(bitwise-not x))
(define/c logand
(case->
(-> any/c any)
(-> #:rest (listof integer?) any))
(case-lambda
[(x) x]
[args (apply bitwise-and args)]))
(define/c logior
(case->
(-> any/c any)
(-> #:rest (listof integer?) any))
(case-lambda
[(x) x]
[args (apply bitwise-ior args)]))
(define/c (logorc1 i j)
[integer? integer? . -> . any]
(logior (lognot i) j))
(define/c (logorc2 i j)
[integer? integer? . -> . any]
(logior i (lognot j)))
(define (binary-logeqv x y) (logand (logorc1 x y) (logorc1 y x)))
(define/c logeqv
(case->
(-> any/c any)
(-> #:rest (listof integer?) any))
(case-lambda
[() -1]
[args (srfi:fold binary-logeqv (car args) (cdr args))]))
(define/c logxor
(case->
(-> any/c any)
(-> #:rest (listof integer?) any))
(case-lambda
[(x) x]
[args (apply bitwise-xor args)]))
(define/c ((rename-out [a:expt expt]) x y) [acl2-number? integer? . -> . any]
(expt x y))
(define/c (characterp x) [any/c . -> . any]
(bool->CL (char? x)))
(define/c (alpha-char-p x) [char? . -> . any]
(bool->CL (char-alphabetic? x)))
(define/c (char-equal c1 c2) [char? char? . -> . any]
(bool->CL (char-ci=? c1 c2)))
(define/c (char< c1 c2) [char? char? . -> . any]
(bool->CL (char<? c1 c2)))
(define/c (char<= c1 c2) [char? char? . -> . any]
(bool->CL (char<=? c1 c2)))
(define/c (char>= c1 c2) [char? char? . -> . any]
(bool->CL (char>=? c1 c2)))
(define/c (char> c1 c2) [char? char? . -> . any]
(bool->CL (char>? c1 c2)))
(define/c (char-code c) [char? . -> . any] (char->integer c))
(define/c (code-char i) [integer? . -> . any] (integer->char i))
(define/c digit-char-p
(case-> (char? . -> . any)
(char? (integer-in 2 36) . -> . any))
(case-lambda
[(x) (or (string->number (string x)) nil)]
[(x base) (or (string->number (string x) base) nil)]))
(define/c (make-character-list chars) [any/c . -> . any]
(let loop ([chars chars]
[result '()])
(cond [(pair? chars) (loop (cdr chars) (cons (if (char? (car chars))
(car chars)
(code-char 0))
result))]
[else (reverse result)])))
(define/c (stringp x) [any/c . -> . any] (bool->CL (string? x)))
(define *standard-chars*
'(#\Newline #\Space #\! #\" #\# #\$
#\% #\& #\' #\( #\) #\* #\+ #\, #\- #\.
#\/ #\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8
#\9 #\: #\; #\< #\= #\> #\? #\@ #\A #\B
#\C #\D #\E #\F #\G #\H #\I #\J #\K #\L
#\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V
#\W #\X #\Y #\Z #\[ #\\ #\] #\^ #\_ #\`
#\a #\b #\c #\d #\e #\f #\g #\h #\i #\j
#\k #\l #\m #\n #\o #\p #\q #\r #\s #\t
#\u #\v #\w #\x #\y #\z #\{ #\| #\} #\~))
(define/c (standard-char-p c) [char? . -> . any]
(if (memq c *standard-chars*) t nil))
(define (standard-string? s)
(and (string? s) (andmap (lambda (x) (memq x *standard-chars*)) (string->list s))))
(define/c (standard-char-listp x) [any/c . -> . any]
(bool->CL (let loop ([x x])
(if (pair? x)
(and (memq (car x) *standard-chars*)
(loop (cdr x)))
(null? x)))))
(define/c (string-equal s1 s2) [standard-string? standard-string? . -> . any]
(bool->CL (string-ci=? s1 s2)))
(define/c (string< s1 s2) [string? string? . -> . any]
(let loop ([posn 0]
[s1 (string->list s1)]
[s2 (string->list s2)])
(cond [(null? s1) (if (null? s2) nil posn)]
[(null? s2) nil]
[(char<? (car s1) (car s2)) posn]
[(char=? (car s1) (car s2)) (loop (add1 posn) (cdr s1) (cdr s2))]
[else nil])))
(define/c (string<= s1 s2) [string? string? . -> . any]
(if (string=? s1 s2) (string-length s1) (string< s1 s2)))
(define/c (string>= s1 s2) [string? string? . -> . any]
(if (string=? s1 s2) (string-length s1) (string> s1 s2)))
(define/c (string> s1 s2) [string? string? . -> . any]
(string< s2 s1))
(define/c (nth n l) (natural-number/c (listof any/c) . -> . any)
(if (>= n (length l)) nil (list-ref l n)))
(define/c (coerce x result-type)
(([x (case result-type
[(list) string?]
[(string) (listof char?)]
[else any/c])] [result-type (symbols 'list 'string)])
()
. ->d . any)
(case result-type
[(list) (string->list x)]
[(string) (list->string x)]))
(define/c (explode-nonnegative-integer n radix rest)
[natural-number/c (or/c (=/c 2) (=/c 8) (=/c 10) (=/c 16)) any/c . -> . any]
(append (string->list (number->string n radix)) rest))
(define/c (acl2-numberp x) [any/c . -> . any]
(bool->CL (acl2-number? x)))
(define/c (natp x) [any/c . -> . any]
(bool->CL (and (integer? x) (<= 0 x))))
(define (complex-rational? val)
(and (complex? val)
(let ([real (real-part val)]
[imag (imag-part val)])
(and (rational? real)
(rational? imag)
(not (zero? imag))))))
(define/c (complex-rationalp x) [any/c . -> . any] (bool->CL (complex-rational? x)))
(define/c (zp x) [natural-number/c . -> . any] (bool->CL (zero? x)))
(define/c (evenp x) [integer? . -> . any] (bool->CL (even? x)))
(define/c (oddp x) [integer? . -> . any] (bool->CL (odd? x)))
(define/c (minusp x) [real/rational? . -> . any] (bool->CL (negative? x)))
(define/c (plusp x) [real/rational? . -> . any] (bool->CL (positive? x)))
(define/c (posp x) [any/c . -> . any] (bool->CL (and (integer? x) (positive? x))))
(define/c (integerp x) (any/c . -> . any) (bool->CL (integer? x)))
(define/c (rationalp x) (any/c . -> . any) (bool->CL (rational? x)))
(define/c (real/rationalp x) (any/c . -> . any) (rationalp x))
(define/c (integer-range-p low high int) (integer? integer? any/c . -> . any)
(bool->CL (and (integer? int)
(<= low int)
(< int high))))
(define/c ((rename-out [a:min min]) x y) [real/rational? real/rational? . -> . any]
(min x y))
(define/c ((rename-out [a:max max]) x y) [real/rational? real/rational? . -> . any]
(max x y))
(define/c (unary-/ x) (non-zero-acl2-number? . -> . any) (/ x))
(define-syntax (macro/ stx)
(syntax-case stx ()
[(_ x) #'(/ x)]
[(_ num den) #'(/ num den)]
[(_ . xs) (raise-syntax-error #f
(format "Expected one or two arguments, but got ~a"
(length (syntax->list #'xs)))
stx)]
[_else (raise-syntax-error
#f "Functions are allowed only in operator position" stx)]))
(provide (rename-out [macro/ /]))
(define/c (nonnegative-integer-quotient num den)
(natural-number/c (and/c natural-number/c (>/c 0)) . -> . any)
(quotient num den))
(define/c ((rename-out [acl2:= =]) x y) (acl2-number? acl2-number? . -> . any)
(bool->CL (= x y)))
(define/c ((rename-out [acl2:< <]) x y) [real/rational? real/rational? . -> . any] (bool->CL (< x y)))
(define/c ((rename-out [acl2:<= <=]) x y) [real/rational? real/rational? . -> . any] (bool->CL (<= x y)))
(define/c ((rename-out [acl2:>= >=]) x y) [real/rational? real/rational? . -> . any] (bool->CL (>= x y)))
(define/c ((rename-out [acl2:> >]) x y) [real/rational? real/rational? . -> . any] (bool->CL (> x y)))
(define/c (fix x) [any/c . -> . any] (if (number? x) x 0))
(define/c ((rename-out [acl2:floor floor]) num den) [real/rational? non-zero-real/rational? . -> . any]
(floor (/ num den)))
(define/c (mod i j) [real/rational? non-zero-real/rational? . -> . any]
(- i (* (acl2:floor i j) j)))
(provide/contract
(rename acl2:not not [any/c . -> . any]))
(define (alist? x)
(or (null? x)
(and (pair? x) (pair? (car x)) (alist? (cdr x)))))
(define/c (alistp x) [any/c . -> . any] (bool->CL (alist? x)))
(define (both pred? x y) (and (pred? x) (pred? y)))
(define (complex/lex<= c1 c2)
(let ([x1 (fix c1)]
[y1 (fix c2)])
(or (< (real-part x1) (real-part y1))
(and (= (real-part x1) (real-part y1))
(< (imag-part x1) (imag-part y1))))))
(define (atom? x) (not (pair? x)))
(define/c (alphorder a b) [atom? atom? . -> . any]
(cond [(both rational? a b) (acl2:<= a b)]
[(both complex-rational? a b) (complex/lex<= a b)]
[(both char? a b) (bool->CL (char<=? a b))]
[(both string? a b) (bool->CL (string<=? a b))]
[(both symbol? a b) (bool->CL (string-ci<=? (symbol->string a) (symbol->string b)))]
[(both null? a b) t]
[(rational? a) t]
[(rational? b) nil]
[(complex-rational? a) t]
[(complex-rational? b) nil]
[(char? a) t]
[(char? b) nil]
[(string? a) t]
[(string? b) nil]
[(symbol? a) t]
[(null? a) t]
[else nil]))
(define/c ((rename-out [a:second second]) x) [(or/c nil/c pair?) . -> . any] (a:cadr x))
(define/c ((rename-out [a:caar caar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:car x)))
(define/c ((rename-out [a:cadr cadr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cdr x)))
(define/c ((rename-out [a:cdar cdar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:car x)))
(define/c ((rename-out [a:cddr cddr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cdr x)))
(define/c ((rename-out [a:third third]) x) [(or/c nil/c pair?) . -> . any] (caddr x))
(define/c ((rename-out [a:caaar caaar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:caar x)))
(define/c ((rename-out [a:caadr caadr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cadr x)))
(define/c ((rename-out [a:cadar cadar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cdar x)))
(define/c ((rename-out [a:caddr caddr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cddr x)))
(define/c ((rename-out [a:cdaar cdaar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:caar x)))
(define/c ((rename-out [a:cdadr cdadr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cadr x)))
(define/c ((rename-out [a:cddar cddar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cdar x)))
(define/c ((rename-out [a:cdddr cdddr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cddr x)))
(define/c ((rename-out [a:fourth fourth]) x) [(or/c nil/c pair?) . -> . any] (cadddr x))
(define/c ((rename-out [a:caaaar caaaar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:caaar x)))
(define/c ((rename-out [a:caaadr caaadr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:caadr x)))
(define/c ((rename-out [a:caadar caadar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cadar x)))
(define/c ((rename-out [a:caaddr caaddr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:caddr x)))
(define/c ((rename-out [a:cadaar cadaar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cdaar x)))
(define/c ((rename-out [a:cadadr cadadr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cdadr x)))
(define/c ((rename-out [a:caddar caddar]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cddar x)))
(define/c ((rename-out [a:cadddr cadddr]) x) [(or/c nil/c pair?) . -> . any] (a:car (a:cdddr x)))
(define/c ((rename-out [a:cdaaar cdaaar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:caaar x)))
(define/c ((rename-out [a:cdaadr cdaadr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:caadr x)))
(define/c ((rename-out [a:cdadar cdadar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cadar x)))
(define/c ((rename-out [a:cdaddr cdaddr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:caddr x)))
(define/c ((rename-out [a:cddaar cddaar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cdaar x)))
(define/c ((rename-out [a:cddadr cddadr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cdadr x)))
(define/c ((rename-out [a:cdddar cdddar]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cddar x)))
(define/c ((rename-out [a:cddddr cddddr]) x) [(or/c nil/c pair?) . -> . any] (a:cdr (a:cdddr x)))