home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d5xx
/
d556
/
scheme2c.lha
/
Scheme2C
/
Scheme-src.lzh
/
scsc
/
miscexp.sc
< prev
next >
Wrap
Text File
|
1991-10-11
|
10KB
|
283 lines
;;; The functions in this file expand those special forms which don't require
;;; gobs of code. The global variables that are visible outside this module
;;; include:
;;;
;* Copyright 1989 Digital Equipment Corporation
;* All Rights Reserved
;*
;* Permission to use, copy, and modify this software and its documentation is
;* hereby granted only under the following terms and conditions. Both the
;* above copyright notice and this permission notice must appear in all copies
;* of the software, derivative works or modified versions, and any portions
;* thereof, and both notices must appear in supporting documentation.
;*
;* Users of this software agree to the terms and conditions set forth herein,
;* and hereby grant back to Digital a non-exclusive, unrestricted, royalty-free
;* right and license under any changes, enhancements or extensions made to the
;* core functions of the software, including but not limited to those affording
;* compatibility with other hardware or software environments, but excluding
;* applications which incorporate this software. Users further agree to use
;* their best efforts to return to Digital any such changes, enhancements or
;* extensions that they make and inform Digital of noteworthy uses of this
;* software. Correspondence should be provided to Digital at:
;*
;* Director of Licensing
;* Western Research Laboratory
;* Digital Equipment Corporation
;* 100 Hamilton Avenue
;* Palo Alto, California 94301
;*
;* This software may be distributed (but not offered for sale or transferred
;* for compensation) to third parties, provided such third parties agree to
;* abide by the terms and conditions of this notice.
;*
;* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
;* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
;* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
;* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
;* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
;* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
;* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
;* SOFTWARE.
(module miscexp)
;;; External and in-line definitions.
(include "plist.sch")
(include "miscexp.sch")
(define QUOTE-CONSTANTS '()) ; A-list for constants.
;;; (f a b c) ==> ($call tail-call f' a' b' c')
;;;
;;; Expands a function call, where x' denotes x expanded by exp-func. The
;;; tail-call flag is set later on calls that could be tail recursive.
;;; Functions with are lambda expressions with optional arguments require
;;; special processing. This is done so TRANSFORM will only have to transform
;;; calls to lambda expressions with a fixed number of elements. Lambda
;;; variables which are bound to functions are also noted here.
(define (CALL-EXP exp exp-func)
(let* ((call (exp-func (car exp) exp-func))
(id (if ($lambda? call) ($lambda-id call) #f)))
(cond (id
(do ((vals (cdr exp) (cdr vals))
(vars (lambda-reqvars id) (cdr vars))
(opt (lambda-optvars id))
(newvars '())
(newvals '())
(const-bnd '()))
((or (null? vars) (not (pair? vals)))
(if const-bnd
(letrec-lambdas const-bnd ($lambda-body call)))
(cond ((and (null? opt) (null? vals) (null? vars))
`($call () ,call ,@(reverse newvals)))
((and opt (islist vals 0))
(set-lambda-reqvars! id
(reverse (cons (car opt) newvars)))
(set-lambda-optvars! id '())
`($call () ,call
,@(reverse newvals)
,(exp-form (call-exp-cons vals)
exp-func)))
(else (expand-error 'call exp))))
(let ((var (car vars))
(val (exp-func (car vals) exp-func)))
(set! newvars (cons var newvars))
(set! newvals (cons val newvals))
(if (and (symbol? val)
(eq? (id-use val) 'constant))
(set! const-bnd (cons var const-bnd)))
(if (and ($lambda? val) (not (id-set! var)))
(name-a-lambda var val)))))
(else
(set! exp (cons call (exp-form-list (cdr exp) exp-func)))
`($call () ,@exp)))))
(define (LETREC-LAMBDAS vars exps)
(if (pair? exps)
(let ((var ($set-id (car exps)))
(val ($set-exp (car exps))))
(if (memq var vars)
(begin (if (and ($lambda? val) (eq? (id-set! var) 1))
(name-a-lambda var val))
(letrec-lambdas vars (cdr exps)))))))
(define (CALL-EXP-CONS vals)
(cond (vals `(cons ,(car vals) ,(call-exp-cons (cdr vals))))
(else ''())))
(define ($CALL? x) ($call? x))
(define ($CALL-TAIL x) ($call-tail x))
(define (SET-$CALL-TAIL! x v) (set-$call-tail! x v))
(define ($CALL-FUNC x) ($call-func x))
(define (SET-$CALL-FUNC! x f) (set-$call-func! x f))
(define ($CALL-ARGL x) ($call-argl x))
(define (SET-$CALL-ARGL! x al) (SET-$CALL-ARGL! x al))
;;; The special form LAP allows the definition of "inline" C code. An inline
;;; function is called by:
;;;
;;; ((lap (vars ... ) <lap code> ...) args ...)
;;;
;;; The arguments will be evaluated and then the values are substituted for
;;; the variables in the lap code. The form returns a tagged scheme pointer
;;; as its value.
;;;
;;; Unless the <lap code> contains the macro SET, then it is assumed that the
;;; code does not change any cells. The macro BOOLEAN converts a C boolean
;;; into a Scheme boolean. When it is the outermost form, it allows some
;;; optimizing transforms.
(define (LAP-EXP exp exp-func)
(if (and (islist exp 3) (islist (cadr exp) 0))
(let* ((vars (cadr exp))
(body (cddr exp))
(set (let loop ((exp body))
(cond ((and (pair? exp) (eq? (car exp) 'set))
#t)
((pair? exp)
(or (loop (car exp)) (loop (cdr exp))))
(else #f)))))
`($lap ,(cond (set 'set)
((and (= (length body) 1)
(pair? (car body))
(eq? (caar body) 'boolean))
'boolean)
(else 'read-only))
,vars
,@body))
(expand-error (car exp) exp)))
(define ($LAP? x) ($lap? x))
(define ($LAP-TYPE x) ($lap-type x))
(define ($LAP-VARS x) ($lap-vars x))
(define ($LAP-BODY x) ($lap-body x))
(define (SET-$LAP-BODY! exp body) (set-$lap-body! exp body))
;;; (quote x) ==> const_<id>
;;;
;;; Quoted objects become constant variables. Multiple occurences of the same
;;; object will share the same variable. Note that some constants are
;;; globally defined so they get turned into a reference to that external
;;; variable.
(define (QUOTE-EXP exp exp-func)
(if (islist exp 2 2)
(let* ((const (cadr exp))
(const-var (assoc const quote-constants)))
(cond ((and const-var (eq? (id-use (cadr const-var)) 'constant))
(cadr const-var))
((eq? const '#t) true-alpha)
((eq? const '()) empty-list-alpha)
((eq? const '#f) false-alpha)
((equal? const "") (bound '$_empty-string))
((equal? const '#()) (bound '$_empty-vector))
(else
(let ((var (newv 'c 'use 'constant 'value const)))
(set! quote-constants
(cons (list const var) quote-constants))
var))))
(expand-error 'quote exp)))
;;; (set! x y) ==> ($set 'x 'y)
;;;
;;; Covert the arguments, set! is retained as a special form.
(define (SET!-EXP exp exp-func)
(if (and (islist exp 3 3) (symbol? (cadr exp)))
(let ((var (exp-func (cadr exp) exp-func))
(value (exp-func (caddr exp) exp-func)))
(set-id-set!! var (if (id-set! var) (+ 1 (id-set! var)) 1))
`($set ,var ,value))
(expand-error 'set exp)))
(define ($SET? x) ($SET? x))
(define ($SET-ID x) ($SET-ID x))
(define ($SET-EXP x) ($SET-EXP x))
(define (SET-$SET-EXP! x e) (SET-$SET-EXP! x e))
;;; (if a b [ c ]) ==> ($if a' b' c')
;;; ==> b'
;;; ==> c'
;;;
;;; Convert the arguments, if is retained as a special form. If the test
;;; turns out to be a constant expression, then only the appropriate leg of
;;; the if will be expanded and retained.
(define (IF-EXP exp exp-func)
(cond ((islist exp 3 4)
(let ((test (exp-func (cadr exp) exp-func))
(true (caddr exp))
(false (if (cdddr exp) (cadddr exp) #f)))
(cond ((and (symbol? test) (eq? (id-use test) 'constant))
(if (id-value test)
(exp-func true exp-func)
(exp-func false exp-func)))
(else `($if ,test
,(exp-func true exp-func)
,(exp-func false exp-func))))))
(else (expand-error 'if exp))))
(define ($IF? x) ($if? x))
(define ($IF-TEST x)($if-test x))
(define (SET-$IF-TEST! x test) (set-$if-test! x test))
(define ($IF-TRUE x) ($if-true x))
(define (SET-$IF-TRUE! x v)(set-$if-true! x v))
(define ($IF-FALSE x) ($if-false x))
(define (SET-$IF-FALSE! x v) (set-$if-false! x v))
;;; Defines come in two flavors:
;;;
;;; (define (f x y ...) body ... ) defines a function.
;;; (define f body) defines a top-level variable.
;;;
;;; The first is converted to a lambda expression and then processed. The
;;; second processed as is. All forms end up as: ($define id body).
(define (DEFINE-EXP exp exp-func)
(if (and (islist exp 3)
(or (symbol? (cadr exp))
(and (pair? (cadr exp)) (symbol? (caadr exp)))))
(let* ((name (cadr exp))
(body (cddr exp))
(var (if (pair? name) (car name) name)))
(set! current-define-name var)
(set! var
(newv var 'use 'global 'module module-name 'defined #t))
(assign-known-name var)
(if (pair? name)
`($define ,var
,(exp-func `(lambda ,(cdr name) ,@body) exp-func))
`($define ,var ,(exp-func (car body) exp-func))))
(expand-error 'define exp)))
(define ($DEFINE? x) ($define? x))
(define ($DEFINE-ID x) ($define-id x))
(define ($DEFINE-EXP x) ($define-exp x))
(define (SET-$DEFINE-EXP! x e) (set-$define-exp! x e))