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
/
lap.sc
< prev
next >
Wrap
Text File
|
1991-10-11
|
16KB
|
471 lines
;;; The functions in this module are used to emit C code. At the
;;; current time, the only functions are to collect the code and then print
;;; it out when each block completes.
;;;
;* 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 lap)
;;; Global code is emitted by calling the following function. As it consists
;;; solely of declarations, no peep-hole optimization need be down.
(define GLOBAL-LAP-CODE '())
(define (EMIT-GLOBAL-LAP code)
(set! global-lap-code (cons code global-lap-code)))
;;; LAP-CODE is a list of the current generated code. As items are cons'ed
;;; onto it, it is in reverse order.
(define LAP-CODE '())
;;; CODE is generated by calling EMIT-CODE with a list which consists
;;; of the operator followed by any operands. At this point, a small
;;; amount of peep-hole optimization is done.
(define (EMIT-LAP code)
(let* ((old lap-code)
(new (peep-lap code)))
(if (and (log? 'peep) (not (equal? new (cons code old))))
(begin (format sc-icode "/* ")
(do ((i (min 1 (- (length old) 1)) (- i 1)))
((negative? i))
(format sc-icode " ~A" (list-ref old i)))
(format sc-icode " ~A~% =>" code)
(do ((i (min 2 (- (length new) 1)) (- i 1)))
((negative? i))
(format sc-icode " ~A" (list-ref new i)))
(format sc-icode " */~%")))))
(define (PEEP-LAP code)
(cond ((null? lap-code)
(set! lap-code (cons code lap-code)))
((eq? (car code) 'LABEL)
(cond ((eq? (caar lap-code) 'LABEL)
; L1 => L1
; L2
(let ((l1 (cadar lap-code))
(l2 (cadr code)))
(set-id-alias! l2 l1)
(set-id-gotos! (resolve-label l2)
(+ (id-gotos (resolve-label l2))
(id-gotos l2)))
(set! code (car lap-code))
(set! lap-code (cdr lap-code))
(emit-lap code)))
((equal? (car lap-code) (list 'goto (cadr code)))
; GOTO L => L
; L
(bump-label-gotos (car lap-code) -1)
(set! lap-code (cdr lap-code))
(emit-lap code))
((and (eq? (caar lap-code) 'goto) (eq? (caadr lap-code) 'if)
(eq? (resolve-label (caddr (cadr lap-code)))
(resolve-label (cadr code))))
; IF TEST GOTO L1 => IF NOT TEST GOTO L2
; GOTO L2 L1
; L1
(let* ((test (cadadr lap-code))
(op (and (pair? test) (car test))))
(bump-label-gotos (cadr lap-code) -1)
(set! test
(if (and (pair? test) (eq? (car test) 'NOT))
(cadr test)
`(NOT ,test)))
(set! lap-code
(cons code
(cons (list 'if test (cadar lap-code))
(cddr lap-code))))))
(else (set! lap-code (cons code lap-code)))))
((and (eq? (car code) 'SET)
(or (and (eq? (cadr code) 'no-value)
(and (not (pair? (caddr code)))
(not (eq? (caddr code) 'tos))))
(eq? (caddr code) 'no-value)
(equal? (cadr code) (caddr code))))
; no-value := x =>
; x := no-value =>
; x := x =>
; Flush Loads or Stores which are "nop's".
#t)
((and lap-code
(or (eq? (caar lap-code) 'goto)
(and (eq? (caar lap-code) 'set)
(eq? (cadar lap-code) 'return)))
(not (memq (car code) '(LIT INDENT LABEL))))
; GOTO L / RETURN => GOTO L / RETURN
; << anything but a label or end >>
#t)
((and (eq? (car code) 'goto) (eq? (caar lap-code) 'label)
(not (eq? (resolve-label (cadr code)) (cadar lap-code))))
; L1 => GOTO L2 (maybe!)
; GOTO L2
(set-id-alias! (cadar lap-code) (resolve-label (cadr code)))
(set-id-gotos! (resolve-label (cadr code))
(+ (id-gotos (resolve-label (cadr code)))
(id-gotos (cadar lap-code))))
(set! lap-code (cdr lap-code))
(emit-lap code))
(else
(bump-label-gotos code 1)
(set! lap-code (cons code lap-code))))
lap-code)
(define (BUMP-LABEL-GOTOS lap incdec)
(let ((label (case (car lap)
((if) (caddr lap))
((goto) (cadr lap))
(else #f))))
(if label
(begin (set! label (resolve-label label))
(set-id-gotos! label (+ (id-gotos label) incdec))))))
(define (SAVE-CURRENT-LAP lap)
(let ((result (list lap-code lap-temps-used lap-temps-free
lap-max-display)))
(if lap
(begin (set! lap-code (list-ref lap 0))
(set! lap-temps-used (list-ref lap 1))
(set! lap-temps-free (list-ref lap 2))
(set! lap-max-display (list-ref lap 3)))
(begin (set! lap-code '())
(set! lap-temps-used '())
(set! lap-temps-free
'( X1 X2 X3 X4 X5 X6 X7 X8 X9
X10 X11 X12 X13 X14 X15 X16 X17 X18 X19
X20 X21 X22 X23 X24 X25 X26 X27 X28 X29
X30 X31 X32 X33 X34 X35 X36 X37 X38 X39
X40 X41 X42 X43 X44 X45 X46 X47 X48 X49
X50 X51 X52 X53 X54 X55 X56 X57 X58 X59
X60 X61 X62 X63 X64 X65 X66 X67 X68 X69
X70 X71 X72 X73 X74 X75 X76 X77 X78 X79
X80 X81 X82 X83 X84 X85 X86 X87 X88 X89
X90 X91 X92 X93 X94 X95 X96 X97 X98 X99))
(set! lap-max-display free-display)))
result))
(define LAP-TEMPS-USED '())
(define LAP-TEMPS-FREE '())
(define LAP-MAX-DISPLAY 0)
(define (USE-LAP-TEMP)
(let ((temp (car lap-temps-free)))
(if (not (memq temp lap-temps-used))
(set! lap-temps-used (cons temp lap-temps-used)))
(set! lap-temps-free (cdr lap-temps-free))
temp))
(define (DROP-LAP-TEMP temp)
(set! lap-temps-free (cons temp lap-temps-free)))
(define (SAVE-LAP-TEMPS) lap-temps-free)
(define (RESTORE-LAP-TEMPS state) (set! lap-temps-free state))
(define DONE-LAP-LAP '())
(define (DONE-LAP lap)
(if global-lap-code
(let ((lap (list global-lap-code '() '() '())))
(set! global-lap-code '())
(done-lap lap)))
(if (log? 'lap)
(begin (format sc-icode "/* ")
(pretty-print-$tree (reverse (car lap)) sc-icode)
(format sc-icode " */~%")))
(set! done-lap-lap lap)
(pplap (reverse (car lap)) (cadr lap) (cadddr lap) sc-icode))
(define (RESOLVE-LABEL label)
(let ((new (id-alias label)))
(if new
(resolve-label new)
label)))
(define (PPLAP laps temps lap-max-display port)
(let ((indent "")
(display-base #f))
(newline port)
(set! pplap-tos #f)
(for-each
(lambda (lap)
(case (car lap)
((LIT)
(display indent port)
(for-each
(lambda (x)
(if (pair? x)
(pplap-call x port)
(display x port))) (cdr lap))
(newline port))
((LABEL)
(let ((label (resolve-label (cadr lap))))
(if (and (eq? label (cadr lap))
(not (zero? (id-gotos label))))
(format port "~a:~%" label))))
((INDENT)
(set! indent (make-string (cadr lap) #\space)))
((PROC)
(display "TSCP " port)
(pplap-call (cdr lap) port)
(newline port)
(when (cddr lap)
(display " TSCP " port)
(pplap-comma-list (cddr lap) port)
(display ";" port)
(newline port)))
((LOCALS)
(when temps
(format port "~aTSCP " indent)
(pplap-comma-list (map vname temps) port)
(format port ";~%"))
(if (cdr lap)
(let ((base (caddr lap)))
(let loop ((x base))
(when (< x lap-max-display)
(format port
"~aTSCP SD~a = DISPLAY( ~a );~%"
indent x x)
(loop (+ x 1))))
(if (not (= base lap-max-display))
(begin (set! display-base base)
(format port
"~aTSCP SDVAL;~%"
indent)))))
(if (or temps display-base) (newline port)))
((GOTO)
(format port "~agoto ~a;~%" indent
(resolve-label (cadr lap))))
((IF)
(format port "~aif ( " indent)
(pplap-call (cadr lap) port)
(if (< (- (write-width port) (write-count port))
20)
(format port "~%~a " indent))
(format port " ) goto ~a;~%"
(resolve-label (caddr lap))))
((SET)
(case (cadr lap)
((NO-VALUE)
(display indent port)
(pplap-call (caddr lap) port)
(format port ";~%"))
((TOS)
(let ((new-tos (subst-tos (caddr lap))))
(if pplap-tos
(report-error
"PPLAP compiler error"))
(set! pplap-tos new-tos)))
((RETURN)
(when display-base
(unless (equal? (caddr lap) "void")
(format port "~aSDVAL = " indent)
(pplap-call (caddr lap) port)
(format port ";~%"))
(let loop ((x display-base))
(when (< x lap-max-display)
(format port
"~aDISPLAY( ~a ) = SD~a;~%"
indent x x)
(loop (+ x 1)))))
(let ((val (if display-base
'("SDVAL")
(cddr lap))))
(display indent port)
(cond ((equal? (caddr lap) "void")
(display "return" port))
(sc-stack-trace
(pplap-call
(cons "POPSTACKTRACE" val)
port))
(else
(pplap-call
(cons "return" val)
port))))
(format port ";~%"))
(else
(display indent port)
(pplap-call (cadr lap) port)
(display " = " port)
(pplap-call (caddr lap) port)
(format port ";~%"))))
(else (display indent port)
(pplap-call lap port)
(format port ";~%"))))
laps)))
(define PPLAP-TOS '())
(define (POP-TOS)
(let ((tos pplap-tos))
(set! pplap-tos #f)
(if tos tos (report-error "POP-TOS compiler error"))))
(define (SUBST-TOS form)
(cond ((eq? form 'tos)
(pop-tos))
((pair? form)
(cons (subst-tos (car form)) (subst-tos (cdr form))))
(else form)))
(define (PPLAP-CALL lap port)
(let ((limit (- (write-width port) 5)))
(cond ((pair? lap)
(cond ((eq? (car lap) 'CSTRING)
(display #\" port)
(for-each
(lambda (c)
(cond ((assq c '((#\tab . #\t)
(#\newline . #\n)
(#\linefeed . #\n)
(#\formfeed . #\f)
(#\return . #\r)
(#\" . #\")
(#\\ . #\\)))
=> (lambda (old.new)
(display #\\ port)
(display (cdr old.new)
port)))
((or (char<? c #\space)
(char>? c #\~))
(display #\\ port)
(display (list->string
(char->dl c 8 3))))
(else (display c port)))
(when (> (write-count port) limit)
(display #\\ port)
(newline port)))
(string->list (cadr lap)))
(display #\" port))
((and (memq (car lap) '(TRUE FALSE NOT))
(eq? (cadr lap) 'TOS))
(pplap-call (list (car lap) (pop-tos)) port))
((and (eq? (car lap) 'NOT) (pair? (cadr lap)))
(let* ((op (caadr lap))
(operands (cdadr lap))
(invert (assq op
'((EQ . NEQ)
(NEQ . EQ)
(TRUE . FALSE)
(FALSE . TRUE)
(LT . GTE)
(GTE . LT)
(GT . LTE)
(LTE . GT)))))
(cond ((eq? op 'NOT)
(pplap-call (car operands) port))
(invert
(pplap-call (cons (cdr invert) operands)
port))
(else (format port "~a( " (car lap))
(pplap-comma-list (cdr lap) port)
(display " )" port)))))
((and (eq? (car lap) 'TRUE) (pair? (cadr lap))
(eq? (caadr lap) 'BOOLEAN))
(pplap-call (cadadr lap) port))
((and (eq? (car lap) 'FALSE) (pair? (cadr lap))
(eq? (caadr lap) 'BOOLEAN))
(pplap-call `(NOT ,(cadadr lap)) port))
(else (pplap-call (car lap) port)
(display "( " port)
(pplap-comma-list (cdr lap) port)
(display " )" port))))
((eq? lap 'TOS)
(pplap-call (pop-tos) port))
((and (symbol? lap) (id-use lap))
(if (not (eq? (vname lap) lap))
(report-error "PPLAP looked up a symbol:" lap))
(display (vname lap) port))
(else (display lap port)))))
(define (PPLAP-COMMA-LIST lap port)
(let* ((indent (write-count port))
(nextline (negative? (pplap-size lap
(- (write-width port) indent)))))
(when lap
(pplap-call (car lap) port)
(when (cdr lap)
(display ", " port)
(when nextline
(newline port)
(set-write-count! port indent))
(pplap-comma-list (cdr lap) port)))))
(define (PPLAP-SIZE lap left)
(cond ((negative? left) left)
((null? lap) left)
((pair? lap)
(if (eq? (car lap) 'CSTRING)
(- left (+ (string-length (cadr lap)) 5))
(pplap-size (cdr lap) (pplap-size (car lap) (- left 4)))))
((eq? lap 'TOS)
(pplap-size pplap-tos left))
(else (- left
(string-length (format "~a.."
(if (and (symbol? lap) (id-use lap))
(vname lap)
lap)))))))
;;; Downshift a symbol name. Leave any other value unchanged.
(define (DOWNSHIFT op)
(if (symbol? op) (string-downcase (symbol->string op)) op))
;;; Initialization for this module is preformed by the following procedure.
(define (LOAD-PLIST-LAP)
(for-each
(lambda (x)
(set-id-vname! x x)
(set-id-use! x '$lexical))
'( X1 X2 X3 X4 X5 X6 X7 X8 X9
X10 X11 X12 X13 X14 X15 X16 X17 X18 X19
X20 X21 X22 X23 X24 X25 X26 X27 X28 X29
X30 X31 X32 X33 X34 X35 X36 X37 X38 X39
X40 X41 X42 X43 X44 X45 X46 X47 X48 X49
X50 X51 X52 X53 X54 X55 X56 X57 X58 X59
X60 X61 X62 X63 X64 X65 X66 X67 X68 X69
X70 X71 X72 X73 X74 X75 X76 X77 X78 X79
X80 X81 X82 X83 X84 X85 X86 X87 X88 X89
X90 X91 X92 X93 X94 X95 X96 X97 X98 X99
TOS NO-VALUE RETURN)))