home *** CD-ROM | disk | FTP | other *** search
- ; prelude.scheme -- UMB Scheme, standard primitives in Scheme.
- ;
- ; Copyright 1988, 1991 University of Massachusetts
- ;
- ; Author: William R Campbell, University of Massachusetts at Boston,
- ;
- ; $Revision: 2.12 $
-
- (gc-messages #f)
-
- ; PRIMITIVE PROCEDURES
-
- ; Pairs and lists.
-
- ; car - cdr compositions (caar pair) ... (cddddr pair)
-
- (define (caar x) (car (car x)))
- (define (cadr x) (car (cdr x)))
- (define (cdar x) (cdr (car x)))
- (define (cddr x) (cdr (cdr x)))
-
- (define (caaar x) (car (car (car x))))
- (define (caadr x) (car (car (cdr x))))
- (define (cadar x) (car (cdr (car x))))
- (define (caddr x) (car (cdr (cdr x))))
- (define (cdaar x) (cdr (car (car x))))
- (define (cdadr x) (cdr (car (cdr x))))
- (define (cddar x) (cdr (cdr (car x))))
- (define (cdddr x) (cdr (cdr (cdr x))))
-
- (define (caaaar x) (car (car (car (car x)))))
- (define (caaadr x) (car (car (car (cdr x)))))
- (define (caadar x) (car (car (cdr (car x)))))
- (define (caaddr x) (car (car (cdr (cdr x)))))
- (define (cadaar x) (car (cdr (car (car x)))))
- (define (cadadr x) (car (cdr (car (cdr x)))))
- (define (caddar x) (car (cdr (cdr (car x)))))
- (define (cadddr x) (car (cdr (cdr (cdr x)))))
- (define (cdaaar x) (cdr (car (car (car x)))))
- (define (cdaadr x) (cdr (car (car (cdr x)))))
- (define (cdadar x) (cdr (car (cdr (car x)))))
- (define (cdaddr x) (cdr (car (cdr (cdr x)))))
- (define (cddaar x) (cdr (cdr (car (car x)))))
- (define (cddadr x) (cdr (cdr (car (cdr x)))))
- (define (cdddar x) (cdr (cdr (cdr (car x)))))
- (define (cddddr x) (cdr (cdr (cdr (cdr x)))))
-
- ; (list obj ...)
-
- (define (list . elems) elems)
-
- ; (list? obj) -- Defined below (after named lets are introduced).
-
- ; (memq obj list)
- ; (memv obj list)
- ; (member obj list)
-
-
- (define (memq obj list)
- (if (null? list) #f
- (if (not (pair? list))
- (error "2nd arg to memq not a list: " list)
- (if (eq? obj (car list)) list
- (memq obj (cdr list)) ))))
-
-
- (define (memv obj list)
- (if (null? list) #f
- (if (not (pair? list))
- (error "2nd arg to memv not a list: " list)
- (if (eqv? obj (car list)) list
- (memv obj (cdr list)) ))))
-
-
- (define (member obj list)
- (if (null? list) #f
- (if (not (pair? list))
- (error "2nd arg to member not a list: " list)
- (if (equal? obj (car list)) list
- (member obj (cdr list)) ))))
-
-
- ; (assq obj alist)
- ; (assv obj alist)
- ; (assoc obj alist)
-
- (define (assq obj alist)
- (if (null? alist) #f
- (if (not (pair? alist))
- (error "2nd argument to assq not a list: " alist)
- (if (eq? (caar alist) obj) (car alist)
- (assq obj (cdr alist))))))
-
-
- (define (assv obj alist)
- (if (null? alist) #f
- (if (not (pair? alist))
- (error "2nd argument to assv not a list: " alist)
- (if (eqv? (caar alist) obj) (car alist)
- (assv obj (cdr alist))))))
-
-
- (define (assoc obj alist)
- (if (null? alist) #f
- (if (not (pair? alist))
- (error "2nd argument to assoc not a list: " alist)
- (if (equal? (caar alist) obj) (car alist)
- (assoc obj (cdr alist))))))
-
- ; Numbers
-
- (define (number->string num . radix )
- (#_number->string num (if (null? radix) 10 (car radix)) ))
-
- (define (string->number str . radix )
- (#_string->number str (if (null? radix) 0 (car radix)) ))
-
- ; Strings
-
- ; (make-string k)
- ; (make-string k char)
-
- (define (make-string length . fill-char)
- (if (null? fill-char)
- (#_make-string length #\space)
- (#_make-string length (car fill-char)) ) )
-
- ; (string char ...)
-
- (define (string . characters) (list->string characters))
-
- ; Vectors
-
- ; (make-vector k)
- ; (make-vector k fill)
-
- (define (make-vector length . fill) ; and extend it to handle default fill
- (#_make-vector length (if (null? fill) (the-undefined-symbol) (car fill)) ))
-
- ; (vector obj ...)
-
- (define (vector . elems) (list->vector elems))
-
-
- ; Control Features
-
- ; (apply proc args)
- ; (apply proc arg1 ... args)
-
- (define (#_collect args)
- (if (null? (cdr args)) (car args) (cons (car args) (#_collect (cdr args)))))
-
- (define (apply proc arg1 . args)
- (#_apply proc (if (null? args) arg1 (#_collect (cons arg1 args)))))
-
-
- ; (map proc list1 list2 ...)
-
- (define (map fn list . lists)
- (if (null? lists) (#_map1 fn list)
- (#_mapn fn (cons list lists))))
-
- (define (#_map1 fn list)
- (if (null? list) '()
- (cons (fn (car list)) (#_map1 fn (cdr list)))))
-
- (define (#_mapn fn lists)
- (if (null? (car lists)) '()
- (cons (#_apply fn (#_map1 car lists))
- (#_mapn fn (#_map1 cdr lists)) )))
-
- ; (for-each proc list1 list2 ...)
-
- (define (for-each proc list . lists)
- (if (null? lists) (#_for-each1 proc list)
- (#_for-eachn proc (cons list lists))))
-
- (define (#_for-each1 proc list)
- (if (null? list) '()
- (begin (proc (car list))
- (#_for-each1 proc (cdr list)))))
-
- (define (#_for-eachn proc lists)
- (if (null? (car lists)) '()
- (begin (#_apply proc (#_map1 car lists))
- (#_for-eachn proc (#_map1 cdr lists)) )))
-
-
- ; Input and output (Ports)
-
- ; (call-with-input-file string proc) DEFINED BELOW
- ; (call-with-output-file string proc) DEFINED BELOW
-
- ; (read)
- ; (read port)
- ; (read-char)
- ; (read-char port)
- ; (peek-char)
- ; (peek-char port)
- ; (char-ready?)
- ; (char-ready? port)
-
- (define (read . port)
- (#_read (if (null? port) (current-input-port) (car port))))
-
- (define (read-char . port)
- (#_read-char (if (null? port) (current-input-port) (car port))))
-
- (define (peek-char . port)
- (#_peek-char (if (null? port) (current-input-port) (car port))))
-
- (define (char-ready? . port)
- (#_char-ready? (if (null? port) (current-input-port) (car port))))
-
- ; (write)
- ; (write port)
- ; (newline)
- ; (newline port)
- ; (write-char)
- ; (write-char port)
-
- (define (write obj . port) ; and extend them to have default ports
- (#_write obj (if (null? port) (current-output-port) (car port))))
-
- (define (display obj . port)
- (#_display obj (if (null? port) (current-output-port) (car port))))
-
- (define (newline . port)
- (if (null? port) (write-char #\newline (current-output-port))
- (write-char #\newline (car port)) ))
-
- (define (write-char obj . port)
- (#_write-char obj (if (null? port) (current-output-port) (car port))))
-
-
- ; (with-input-from-file string thunk) DEFINED BELOW
- ; (with-output-to-file string thunk) DEFINED BELOW
-
- ; DERIVED EXPRESSION TYPES
-
- ; (quasi-quote <template>)
- ; `<template> ==> (quasiquote <template>) in (read)
-
- (macro quasiquote
- (lambda (form)
- (#_quasiquote (cadr form))))
-
- (define (#_quasiquote skel)
- (if (vector? skel) (list 'list->vector (#_quasiquote (vector->list skel)))
- (if (null? skel) ''()
- (if (symbol? skel) (list 'quote skel)
- (if (not (pair? skel)) skel
- (if (eq? (car skel) 'unquote) (cadr skel)
- (if (eq? (car skel) 'quasiquote)
- (#_quasiquote (#_quasiquote (cadr skel)))
- (if (if (pair? (car skel))
- (eq? (caar skel) 'unquote-splicing) #f)
- (list 'append (cadar skel)
- (#_quasiquote (cdr skel)))
- (#_combine-skels (#_quasiquote (car skel))
- (if (null? (cdr skel)) '()
- (#_quasiquote (cdr skel)))
- skel)
- ))))))))
-
-
- (define (#_combine-skels lft rgt skel)
- (if (if (#_isconst? lft) (#_isconst? rgt) #f) (list 'quote skel)
- (if (null? rgt) (list 'list lft)
- (if (if (pair? rgt) (eq? (car rgt) 'list) #f)
- (cons 'list (cons lft (cdr rgt)))
- (list 'cons lft rgt)
- ))))
-
-
- (define (#_isconst? obj)
- (if (pair? obj) (eq? (car obj) 'quote) #f))
-
-
- ; (defmacro (key name) ...) => (macro key (lambda (name) ...))
-
- (macro defmacro
- (lambda (x)
- `(macro ,(caadr x) (lambda (,(cadadr x)) ,@(cddr x))) ))
-
- (defmacro (let form)
- (if (symbol? (cadr form))
-
- ; a named let
- ; (let v0 ((v1 e1) ...) . body)
- ; =>
- ; ((letrec ((v0 (lambda (v1 ...) . body)))
- ; v0)
- ; e1 ...)
-
- `((letrec ((,(cadr form) (lambda ,(#_map1 car (caddr form))
- ,@(cdddr form) )))
- ,(cadr form))
- ,@(#_map1 cadr (caddr form)) )
-
- ; a regular let
- ; (let ((v1 e1) ...) . body)
- ; =>
- ; ((lambda (v1 ...) . body) e1 ...)
-
- `( (lambda ,(#_map1 car (cadr form)) ,@(cddr form))
- ,@(#_map1 cadr (cadr form))) ))
-
-
- ; (and) => #t
- ; (and e1) => e1
- ; (and e1 e2 ...) =>
- ; (let ((x e1)
- ; (thunk (lambda()(and e2...))))
- ; (if x (thunk) x))
-
- (defmacro (and form)
- (if (null? (cdr form)) #t
- (if (null? (cddr form)) (cadr form)
- (let ((x (gensym "_x"))
- (thunk (gensym "_thunk")))
- `(let ((,x ,(cadr form))
- (,thunk (lambda ()
- (and ,@(cddr form)))))
- (if ,x (,thunk) ,x))
- ))))
-
-
- ; (or) => #f
- ; (or e1) => e1
- ; (or e1 e2 ...) =>
- ; (let ((x e1)
- ; (thunk (lambda()(or e2...))))
- ; (if x x (thunk)))
-
-
- (defmacro (or form)
- (if (null? (cdr form)) #f
- (if (null? (cddr form)) (cadr form)
- (let ((x (gensym "_x"))
- (thunk (gensym "_thunk")))
- `(let ((,x ,(cadr form))
- (,thunk (lambda ()
- (or ,@(cddr form)))))
- (if ,x ,x (,thunk)))
- ))))
-
- ; (cond) => '()
- ;
- ; (cond (else seq)) => (begin seq)
- ;
- ; (cond (e1) c2 ...) => (or e1 (cond c2 ...))
- ;
- ; (cond (e1 => recipient) c2 ...) =>
- ; (let ((t e1)
- ; (r (lambda() recipient))
- ; (c (lambda() c2 ...)))
- ; (if t ((r)t) (c)) )
- ;
- ; (cond (e1 seq1) c2 ...) =>
- ; (if e1 (begin seq1)
- ; (cond c2 ...))
-
- (defmacro (cond form)
- (if (null? (cdr form)) ''()
- (let ((c1 (cadr form)))
- (if (not (pair? c1))
- (error "Bad cond syntax: " form)
- (if (eq? (car c1) 'else)
- `(begin ,@(cdr c1))
- (if (null? (cdr c1))
- `(or ,(car c1)
- (cond ,@(cddr form)))
- (if (eq? (cadr c1) '=>)
- (let ((t (gensym "_t"))
- (r (gensym "_r"))
- (c (gensym "_c")))
- `(let ((,t ,(car c1))
- (,r (lambda () ,@(cddr c1)))
- (,c (lambda () (cond ,@(cddr form)))))
- (if ,t ((,r),t) (,c))) )
- `(if ,(car c1)
- (begin ,@(cdr c1))
- (cond ,@(cddr form)))
- )))))))
-
-
- ; (let* ((v1 e1) ...) body) => (let ((v1 e1)) (let* ( ... ) body))
- ;
- ; (let* () body) => (begin body)
-
- (defmacro (let* form) ;
- (if (not (pair? (cdr form)))
- (error "Bad let* syntax: " form)
- (if (null? (cadr form))
- `(begin ,@(cddr form))
- (if (and (pair? (cadr form)) (pair? (caadr form))
- (pair? (cdaadr form)))
- `(let (( ,(caaadr form) ,(car (cdaadr form)) ))
- (let* ,(cdadr form) ,@(cddr form)))
- (error "Bad let* syntax: " form) ))))
-
- ; (letrec ((var1 e1) ...)
- ; body)
- ;
- ; =>
- ;
- ; (let ((var1 #f) ...)
- ; (let ((temp1 expression1) ...)
- ; (set! var1 temp1) ...)
- ; body)
- ;
- ; NB: We don't actually implement the inner let since it's not
- ; strictly neccessary.
-
- (defmacro (letrec form) ; form = (letrec ((v1 e1)...) . body)
- (let ((vars (#_map1 car (cadr form)))
- (temps (#_map1 (lambda (x) (gensym "_temp")) (cadr form)))
- (exprs (#_map1 cadr (cadr form)))
- (body (cddr form)) )
- `(let (,@(#_map1 (lambda (x) `(,x #f)) vars))
- (let (,@(map (lambda (x y) `(,x ,y)) temps exprs))
- ,@(map (lambda (x y) `(set! ,x ,y)) vars temps)
- ,@body )) ))
-
-
- ; (case key
- ; ((d1 ...) seq)
- ; ...)
- ;
- ; =>
- ;
- ; (let ((keyvar key))
- ; (cond ((memv keyvar '(d1 ...)) seq)
- ; ...)
- ;
- ; Note: the clause, (else seq) => (else seq)
-
- (defmacro (case form)
- (let ((keyvar (gensym "_keyvar"))
- (key (cadr form))
- (clauses (cddr form)))
- `(let ((,keyvar ,key))
- (cond
- ,@(map (lambda (c)
- (if (eqv? (car c) 'else) c
- `((memv ,keyvar (quote ,(car c))) ,@(cdr c)) ))
- clauses) )) ))
-
-
- ; (do ((var1 init1 step1) ...)
- ; (test seq)
- ; cmd1 ...)
- ;
- ; =>
- ;
- ; (letrec ((loop
- ; (lambda (var1 ...)
- ; (if test
- ; (begin seq)
- ; (begin cmd1
- ; ...
- ; (loop step1 ...))))))
- ; (loop init1 ...))
-
- (defmacro (do form)
- (let ((loop (gensym "_loop"))
- (vars (map car (cadr form)))
- (inits (map cadr (cadr form)))
- (steps (map (lambda (l) (if (= (length l) 3)
- (caddr l)
- (car l)))
- (cadr form)))
- (test (caaddr form))
- (seq (cdaddr form))
- (cmds (cdddr form)))
- `(letrec ((,loop
- (lambda ,vars
- (if ,test
- (begin ,@seq)
- (begin ,@cmds (,loop ,@steps))))))
- (,loop ,@inits)) ))
-
- ; PRIMITIVES requiring syntax defined above.
-
- ; (list? obj)
-
- (define (list? x)
- (cond ((null? x) #t)
- ((not (pair? x)) #f)
- ((null? (cdr x)) #t)
- ((not (pair? (cdr x))) #f)
- (else (let loop ((fast (cddr x)) (slow (cdr x)))
- (cond ((null? fast) #t)
- ((or (not (pair? fast)) (eq? fast slow)) #f)
- ((null? (cdr fast)) #t)
- (else (loop (cddr fast) (cdr slow))))))))
-
- ; (call-with-input-file string proc)
- ; (call-with-output-file string proc)
-
- (define (call-with-input-file string proc )
- (let* ((port (open-input-file string))
- (result (proc port)))
- (close-input-port port)
- result))
-
- (define (call-with-output-file string proc )
- (let* ((port (open-output-file string))
- (result (proc port)))
- (close-output-port port)
- result))
-
- ; (with-input-from-file string thunk)
- ; (with-output-to-file string thunk)
-
- (define (with-input-from-file string thunk)
- (let ((save (current-input-port))
- (port (open-input-file string)))
- (set-current-input-port! port)
- (let ((result (thunk)))
- (close-input-port port)
- (set-current-input-port! save)
- result)))
-
- (define (with-output-to-file string thunk)
- (let ((save (current-output-port))
- (port (open-output-file string)))
- (set-current-output-port! port)
- (let ((result (thunk)))
- (close-output-port port)
- (set-current-output-port! save)
- result)))
-
- ; ERROR HANDLING
-
- (defmacro (break form)
- (if (null? (cdr form))
- '(#_break)
- `(begin (display* ,@(cdr form)) (newline) (break)) ))
-
- (define (error . args )
- (newline)
- (display "Error: ")
- (apply display* args)
- (newline)
- (break) )
-
- ; DEBUGGING
-
- (define (show-env . args)
- (#_show-env (if (null? args) 20 (car args))))
-
- (define (where . args)
- (#_where (if (null? args) 20 (car args))))
-
- (define (go arg . rest)
- (if (null? rest) (#_go 0 arg) (#_go arg (car rest))))
-
- (defmacro (how form)
- `(#_how (quote ,(cadr form))))
-
- ; EDITING
-
- ; Define edit to remember the last file edited.
-
- (define #_last-file-edited '())
-
- ; (edit)
- ; (edit filename)
-
- (define (edit . filestring)
- (if (null? filestring)
- (if (null? #_last-file-edited)
- (error "(edit) not previously applied -- no file to remember.")
- (#_edit #_last-file-edited))
- (begin
- (set! #_last-file-edited (car filestring))
- (#_edit (car filestring))) ))
-
- ; (edits)
- ; (edits filename)
-
- (define (edits . filestring)
- (if (null? filestring)
- (if (null? #_last-file-edited)
- (error "(edits) not previously applied -- no file to remember.")
- (#_edits #_last-file-edited))
- (begin
- (set! #_last-file-edited (car filestring))
- (#_edits (car filestring))) ))
-
- ; UMB SPECIFIC
-
- (define (write* first . rest)
- (define port (if (output-port? first) first (current-output-port)))
- (define (write** objs)
- (if (pair? objs)
- (begin (#_write (car objs) port) (write** (cdr objs)))))
- (write** (if (output-port? first) rest (cons first rest))))
-
-
- (define (display* first . rest)
- (define port (if (output-port? first) first (current-output-port)))
- (define (display** objs)
- (if (pair? objs)
- (begin (#_display (car objs) port) (display** (cdr objs)))))
- (display** (if (output-port? first) rest (cons first rest))))
-
-
-
- ; PROCEDURES SUPPORTING THE ABLESON AND SUSSMAN TEXT
-
- (defmacro (cons-stream form)
- `(cons ,(cadr form) (delay ,(caddr form))))
-
- (define head car)
- (define (tail stream) (force (cdr stream)))
-
- (defmacro (extend-environment form)
- `(let ,(map (lambda (defn)
- (if (and (list? defn) (= (length defn) 3)
- (eq? (car defn) 'define))
- (cdr defn)
- (error "Bad definition in an extend-environment form")))
- (cdr form))
- (current-environment)))
-
-
-
- ; MAINTENANCE PROCEDURES
-
- ; (expand-macro-call calling-form) -- code from expansion
-
- (defmacro (expand-macro-call form)
- `(expand-quoted-macro-call (quote ,(cadr form))))
-
- ; (vi) -- edit this file
-
- (define (vi) (edit "prelude.scheme"))
-
- ; (factorial n) -- for demonstrating bignums
-
- (define (factorial n)
- (if (<= n 0) 1
- (* n (factorial (- n 1))) ))
-
-
- (define (foo x y z)
- ( (lambda (a b c) (+ (break) (+ x y z))) z y x) )
-
- (define (divby x) (/ 100 x))
-
- (define (goo n)
- (if (= n 0) 1 (* 10 (goo (- n 1))) ))
-
- (gc-messages #t)
-