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
/
misccode.sc
< prev
next >
Wrap
Text File
|
1991-10-11
|
12KB
|
337 lines
;;; Code generator for symbols and $set, $if, and $define expressions.
;;;
;* 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 misccode)
;;; External and in-line declarations.
(include "plist.sch")
(include "expform.sch")
(include "lambdaexp.sch")
(include "miscexp.sch")
(include "gencode.sch")
(include "lap.sch")
;;; identifier
;;;
;;; Load it's value into the location.
(define (SYMBOL-GENC loc exp bindings)
(let ((var (lookup exp bindings))
(c-type (and (eq? (id-use exp) 'global) (id-type exp))))
(cond ((eq? loc 'no-value)
#f)
(c-type
(emit-lap
`(SET ,(vname loc)
,(case c-type
((char) `(CHAR_TSCP ,var))
((int) `(INT_TSCP ,var))
((shortint longint) `(INT_TSCP (INT ,var)))
((unsigned) `(UNSIGNED_TSCP ,var))
((shortunsigned longunsigned)
`(UNSIGNED_TSCP (UNSIGNED ,var)))
((pointer) `(POINTER_TSCP ,var))
((tscp) var)
((float) `(DOUBLE_TSCP (CDOUBLE ,var)))
((double) `(DOUBLE_TSCP ,var))
(else (report-error
"Cannot load value of"
(id-printname exp)))))))
(else (emit-lap `(SET ,(vname loc) ,var))))))
;;; ($define var exp)
;;;
;;; Emit code to declare the global variable, evaluate its initial value,
;;; and inform the run-time system of its existence.
(define ($DEFINE-GENC loc exp bindings)
(let* ((name ($define-id exp))
(body ($define-exp exp))
(temp (make-c-global))
(string-name (symbol->string (id-printname name))))
(set! current-define-name (id-printname name))
(emit-global-lap `(DEFTSCP ,(vname name)))
(if (not (or (eq? top-level-symbols #t)
(memq (id-printname name) top-level-symbols)))
(set! string-name
(string-append module-name-upcase "_" string-name)))
(emit-global-lap `(DEFSTRING ,(vname temp)
(CSTRING ,string-name)
,(string-length string-name)))
(set! current-define-string temp)
(exp-genc 'tos body bindings)
(set-id-external! name #t)
(emit-lap `(INITIALIZEVAR (U_TX (ADR ,(vname temp)))
(ADR ,(vname name)) tos))
(set! current-define-name 'top-level)))
;;; ($set var exp)
;;;
;;; Emit code for expression and store it in var. Note the special case
;;; for procedures.
(define ($SET-GENC loc exp bindings)
(let* ((var ($set-id exp))
(set (if (var-in-stack var)
'SETGEN
(if (var-is-top-level var)
'SETGENTL
'SET)))
(c-type (and (eq? (id-use var) 'global) (id-type var))))
(cond ((and (id-lambda var)
(not (eq? (lambda-generate (id-lambda var))
'closed-procedure)))
(exp-genc 'no-value ($set-exp exp) bindings))
(c-type
(let ((temp (if (eq? loc 'no-value) 'tos (use-lap-temp))))
(exp-genc temp ($set-exp exp) bindings)
(emit-lap `(SET tos ,(vname temp)))
(emit-lap
`(SET ,(lookup var bindings)
,(case c-type
((char) '(TSCP_CHAR tos))
((int) '(TSCP_INT tos))
((tscp) 'tos)
((shortint) '(SHORTINT (TSCP_INT tos)))
((longint) '(LONGINT (TSCP_INT tos)))
((unsigned) '(TSCP_UNSIGNED tos))
((shortunsigned)
'(SHORTUNSIGNED (TSCP_UNSIGNED tos)))
((longunsigned)
'(LONGUNSIGNED (TSCP_UNSIGNED tos)))
((pointer) '(TSCP_POINTER tos))
((float) '(CFLOAT (TSCP_DOUBLE tos)))
((double) '(TSCP_DOUBLE tos)))))
(unless (eq? temp 'tos)
(emit-lap `(SET ,(vname loc) ,(vname temp)))
(drop-lap-temp temp))))
(else (let ((temp (if (eq? set 'setgen) (use-lap-temp) 'tos)))
(exp-genc temp ($set-exp exp) bindings)
(if (eq? loc 'no-value)
(emit-lap `(,SET ,(lookup var bindings) ,temp))
(emit-lap
`(SET ,(vname loc)
(,SET ,(lookup var bindings) ,temp))))
(unless (eq? temp 'tos) (drop-lap-temp temp)))))))
;;; ($if test true false)
;;;
;;; Emit code for $if expression. If the test condition has been performed
;;; before, then optimization can be done by taking the one leg that is
;;; known to be true and ignoring the other one that is known to be false.
(define ($IF-GENC loc exp bindings)
(let ((test ($if-test exp))
(true ($if-true exp))
(false ($if-false exp)))
(if (and ($call? test)
($lap? ($call-func test))
(not (args-set!? ($call-argl test))))
(begin
(cond (($call-tested-true-before? test)
(exp-genc loc true bindings))
(($call-tested-false-before? test)
(exp-genc loc false bindings))
(else ($if-genc-no-optimize loc exp bindings test))))
($if-genc-no-optimize loc exp bindings #f))))
;;; Generate code for evaluating the test and then branching appropriately.
;;; The branch condition will be reversed when the true leg is returning a
;;; variable value.
(define ($IF-GENC-NO-OPTIMIZE loc exp bindings add-test)
(let* ((l1 (make-label))
(l2 (make-label))
(test ($if-test exp))
(true ($if-true exp))
(false ($if-false exp))
(t/f-reversed #f)
(tleg-condition '(()))
(fleg-condition '(()))
(save-condition global-condition-info)
(temp (if (eq? loc 'tos) (use-lap-temp) loc)))
(exp-genc 'tos test bindings)
(cond ((and (symbol? true) (memq loc '(return no-value)))
(emit-lap `(IF (TRUE tos) ,l1))
(set! false true)
(set! true ($if-false exp))
(set! t/f-reversed #t))
(else (emit-lap `(IF (FALSE tos) ,l1))))
(if add-test
(add-condition add-test (not t/f-reversed)))
(exp-genc temp true bindings)
(set! tleg-condition global-condition-info)
(set! global-condition-info save-condition)
(if add-test
(add-condition add-test t/f-reversed))
(if (or (not (eq? loc 'no-value)) (not (symbol? false)))
(begin (if (not (eq? loc 'return)) (emit-lap `(GOTO ,l2)))
(emit-lap `(LABEL ,l1))
(exp-genc temp false bindings)
(if (not (eq? loc 'return)) (emit-lap `(LABEL ,l2))))
(emit-lap `(LABEL ,l1)))
(when (eq? loc 'tos)
(emit-lap `(SET tos ,(vname temp)))
(drop-lap-temp temp))
(set! fleg-condition global-condition-info)
(set! global-condition-info save-condition)
(cond ((if-leg-has-no-return? true)
(combine-with-global-condition-info fleg-condition))
((if-leg-has-no-return? false)
(combine-with-global-condition-info tleg-condition))
(else
(combine-with-global-condition-info
(intersect2 tleg-condition fleg-condition))))))
;; The following are operations that pertain to code optimization by
;; elimination of unnecessary $if test conditions that have been tested
;; for already.
(define (CONDITION-INFO-TRUE-LIST x) (car x))
(define (CONDITION-INFO-FALSE-LIST x) (cdr x))
(define (STORE-CONDITION-INFO id)
(put id 'condition-info global-condition-info))
(define (RETRIEVE-CONDITION-INFO id)
(let ((stored-info (get id 'condition-info)))
(if stored-info
stored-info
empty-condition-info)))
(define (UPDATE-CONDITION-INFO id)
(let ((stored-info (get id 'condition-info)))
(if (null? stored-info)
(put id 'condition-info global-condition-info)
(put id 'condition-info
(intersect2 stored-info global-condition-info)))))
(define (COMBINE-WITH-GLOBAL-CONDITION-INFO info . info-list)
(if (null? info-list)
(set! global-condition-info (combine2 info global-condition-info))
(combine-with-global-condition-info (combine2 info (car info-list))
(cdr info-list))))
(define (COMBINE2 info1 info2)
(cons (list-combination (condition-info-true-list info1)
(condition-info-true-list info2))
(list-combination (condition-info-false-list info1)
(condition-info-false-list info2))))
(define (LIST-COMBINATION lst1 lst2)
(if (null? lst2)
lst1
(list-combination (append `(,(car lst2))
(remove (car lst2) lst1))
(cdr lst2))))
(define (INTERSECT-WITH-GLOBAL-CONDITION-INFO info . info-list)
(if (null? info-list)
(set! global-condition-info (intersect2 info global-condition-info))
(intersect-with-global-condition-info (intersect2 info (car info-list))
(cdr info-list))))
(define (INTERSECT2 info1 info2)
(cons (list-intersection (condition-info-true-list info1)
(condition-info-true-list info2))
(list-intersection (condition-info-false-list info1)
(condition-info-false-list info2))))
(define (LIST-INTERSECTION lst1 lst2)
(if (null? lst1)
'()
(if (member (car lst1) lst2)
(append `(,(car lst1)) (list-intersection (cdr lst1) lst2))
(list-intersection (cdr lst1) lst2))))
(define (STORED-CONDITIONS-INTERSECTION lid-list)
(define (iter info info-list)
(if (null? info-list)
info
(iter (intersect2 info (car info-list)) (cdr info-list))))
(let ((stored-info-list (remove '()
(map (lambda (lid) (retrieve-condition-info lid))
lid-list))))
(if (null? stored-info-list)
empty-condition-info
(iter (car stored-info-list) (cdr stored-info-list)))))
(define ($CALL-TESTED-TRUE-BEFORE? test)
(member test (condition-info-true-list global-condition-info)))
(define ($CALL-TESTED-FALSE-BEFORE? test)
(member test (condition-info-false-list global-condition-info)))
(define (ADD-CONDITION test t/f-flag)
(if t/f-flag
; add true condition
(set! global-condition-info
(cons (append `(,test)
(remove test
(condition-info-true-list
global-condition-info)))
(condition-info-false-list global-condition-info)))
; otherwise add false condition
(set! global-condition-info
(cons (condition-info-true-list global-condition-info)
(append `(,test)
(remove test
(condition-info-false-list
global-condition-info)))))))
(define (ARGS-SET!? argl)
(if (null? argl)
#f
(let ((first-arg (car argl))
(rest-args (cdr argl)))
(if (symbol? first-arg)
(or (not (or (eq? (id-use first-arg) 'LEXICAL)
(eq? (id-use first-arg) 'CONSTANT)))
(id-set! first-arg)
(args-set!? rest-args))
#t))))
(define (IF-LEG-HAS-NO-RETURN? leg)
(and ($call? leg)
(member ($call-func leg) `(,error-id ,$_car-error-id ,$_cdr-error-id))))