home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacFormat 1994 November
/
macformat-018.iso
/
Utility Spectacular
/
Developer
/
macgambit-20-compiler-src-p2
/
Runtime (.scm & .s)
/
_eval.scm
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Text File
|
1994-07-26
|
81.0 KB
|
2,469 lines
|
[
TEXT/gamI
]
(##include "header.scm")
;------------------------------------------------------------------------------
(##define-macro (global-env-loc x) `(##global-var ,x))
(##define-macro (global-env-ref x) `(##global-var-ref ,x))
(##define-macro (global-env-set! x y) `(##global-var-set! ,x ,y))
(##define-macro (global-env-loc->var x) `(##index->global-var-name ,x))
(##define-macro (quasi-list->vector x) `(##quasi-list->vector ,x))
(##define-macro (quasi-append x y) `(##quasi-append ,x ,y))
(##define-macro (quasi-cons x y) `(##quasi-cons ,x ,y))
(##define-macro (true? x) x)
(##define-macro (unbound? x) `(##unbound? ,x))
(##define-macro (unspecified-obj) '##undef-object)
(##define-macro (set!-ret-obj) '##unprint-object)
(define ##self-var (##string->uninterned-symbol "<self>"))
(define ##selector-var (##string->uninterned-symbol "<selector>"))
(define ##do-loop-var (##string->uninterned-symbol "<do-loop>"))
(##define-macro (self-var) '##self-var)
(##define-macro (selector-var) '##selector-var)
(##define-macro (do-loop-var) '##do-loop-var)
(##define-macro (rt-error-unbound-global-var code rte)
`(##signal '##SIGNAL.GLOBAL-UNBOUND ,code ,rte))
(##define-macro (rt-error-non-procedure-send code rte)
`(##signal '##SIGNAL.NON-PROCEDURE-SEND ,code ,rte))
(##define-macro (rt-error-non-procedure-oper code rte)
`(##signal '##SIGNAL.NON-PROCEDURE-OPERATOR ,code ,rte))
(##define-macro (rt-error-too-few-args proc args)
`(##signal '##SIGNAL.WRONG-NB-ARG ,proc ,args))
(##define-macro (rt-error-too-many-args proc args)
`(##signal '##SIGNAL.WRONG-NB-ARG ,proc ,args))
(##define-macro (ct-error-global-env-overflow var)
`(##signal '##SIGNAL.GLOBAL-ENV-OVERFLOW ,var))
(##define-macro (ct-error-syntax msg . args)
`(##signal '##SIGNAL.SYNTAX-ERROR src ,msg ,@args))
;------------------------------------------------------------------------------
; Macro to create a node of executable code
(##define-macro (mk-code code-prc subcodes . lst)
(let ((n (+ (length subcodes) (length lst))))
`(let (($code (##make-vector ,(+ n 2) #f)))
(##vector-set! $code 0 #f)
(##vector-set! $code 1 ,code-prc)
,@(let loop1 ((l subcodes) (i 2) (r '()))
(if (pair? l)
(loop1 (cdr l)
(+ i 1)
(cons `(##vector-set! $code ,i (link-to ,(car l) $code)) r))
(let loop2 ((l lst) (i i) (r r))
(if (pair? l)
(loop2 (cdr l)
(+ i 1)
(cons `(##vector-set! $code ,i ,(car l)) r))
(reverse r)))))
$code)))
(##define-macro (link-to child parent)
`(let (($child ,child)) (##vector-set! $child 0 ,parent) $child))
(##define-macro (code-link c) `(##vector-ref ,c 0))
(##define-macro (code-cprc c) `(##vector-ref ,c 1))
(##define-macro (code-length c) `(##fixnum.- (##vector-length ,c) 2))
(##define-macro (code-ref c n) `(##vector-ref ,c (##fixnum.+ ,n 2)))
(##define-macro (code-set! c n x) `(##vector-set! ,c (##fixnum.+ ,n 2) ,x))
(##define-macro (^ n) `(##vector-ref $code ,(+ n 2)))
(define (##mk-code* code-prc lst n)
(let (($code (##make-vector (##fixnum.+ (##length lst) (##fixnum.+ n 2)) #f)))
(##vector-set! $code 0 #f)
(##vector-set! $code 1 code-prc)
(let loop ((i 0) (l lst))
(if (##pair? l)
(begin
(code-set! $code i (link-to (##car l) $code))
(loop (##fixnum.+ i 1) (##cdr l)))
$code))))
(##define-macro (code-run c)
`(let (($$code ,c))
((##vector-ref $$code 1) $$code rte)))
; Macro to create the "code procedure" associated with a code node
(##define-macro (mk-cprc . def)
`(lambda ($code rte) ,@def))
(##define-macro (mk-gen params . def)
`(lambda (cte src tail? ,@params) ,@def))
(##define-macro (gen proc . args)
`(,proc cte src tail? ,@args))
;==============================================================================
; Compiler
;------------------------------------------------------------------------------
; Compile time environment manipulation
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Macros to manipulate the compile time environment
(##define-macro (mk-loc-access up over) `(##cons ,up ,over))
(##define-macro (loc-access? x) `(##pair? ,x))
(##define-macro (loc-access-up x) `(##car ,x))
(##define-macro (loc-access-over x) `(##cdr ,x))
(##define-macro (mk-glo-access var)
`(or (global-env-loc ,var)
(ct-error-global-env-overflow ,var)))
(##define-macro (glo-access? x)
`(##not (##pair? ,x)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Initial global environment
(define ##global-env-macros (##cons (##cons #f #f) '()))
(define ##global-env-decls (##cons '() '()))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##make-cte frames)
(let ((v (##make-vector 3 #f)))
(##vector-set! v 0 frames)
(##vector-set! v 1 ##global-env-macros)
(##vector-set! v 2 ##global-env-decls)
v))
(define (##cte-frames cte) (##vector-ref cte 0))
(define (##cte-macros cte) (##vector-ref cte 1))
(define (##cte-decls cte) (##vector-ref cte 2))
(define (##cte-push-frame cte frame)
(let ((v (##make-vector 3 #f)))
(##vector-set! v 0 (##cons frame (##cte-frames cte)))
(##vector-set! v 1 (##cte-macros cte))
(##vector-set! v 2 (##cte-decls cte))
v))
(define (##cte-push-macro cte name proc)
(let ((v (##make-vector 3 #f)))
(##vector-set! v 0 (##cte-frames cte))
(##vector-set! v 1 (##cons (##cons name proc) (##cte-macros cte)))
(##vector-set! v 2 (##cte-decls cte))
v))
(define (##cte-push-decl cte decl)
(let ((v (##make-vector 3 #f)))
(##vector-set! v 0 (##cte-frames cte))
(##vector-set! v 1 (##cte-macros cte))
(##vector-set! v 2 (##append decl (##cte-decls cte)))
v))
(define (##cte-add-global-macro name proc)
(let ((x (##cdr ##global-env-macros)))
(let ((y (##assq name x)))
(if y
(##set-cdr! y proc)
(##set-cdr! ##global-env-macros
(##cons (##cons name proc) (##cdr ##global-env-macros)))))))
(define (##cte-add-global-decl decl)
(##set-cdr! ##global-env-decls
(##append decl (##cdr ##global-env-decls))))
(define (##cte-lookup-var cte var)
(define (lookup e up)
(if e
(let ((x (##memq var (##car e))))
(if x
(mk-loc-access
up
(##fixnum.+ (##fixnum.- (##length (##car e)) (##length x)) 1))
(lookup (##cdr e) (##fixnum.+ up 1))))
(mk-glo-access var)))
(lookup (##cte-frames cte) 0))
(define ##macro? #f)
(set! ##macro?
(lambda (cte name)
(and (##symbol? name)
(##assq name (##cte-macros cte)))))
(set! ##macro-expand #f)
(define ##macro-expand
(lambda (cte src)
(let ((x (##car src)))
(touch-vars (x)
(##apply (##cdr (##assq x (##cte-macros cte)))
(##cdr src))))))
;------------------------------------------------------------------------------
; Utilities
(define (##self-eval? val)
(touch-vars (val)
(or (##complex? val)
(##string? val)
(##char? val)
(##eq? val #f)
(##eq? val #t))))
(define (##variable src x)
(if (##not (##symbol? x))
(ct-error-syntax "Identifier expected:" x))
(if (##memq x
'(QUOTE QUASIQUOTE UNQUOTE UNQUOTE-SPLICING LAMBDA IF SET!
COND => ELSE AND OR CASE LET LET* LETREC BEGIN DO DEFINE
DELAY FUTURE ##DECLARE ##DEFINE-MACRO ##INCLUDE))
(ct-error-syntax "Variable name can not be a syntactic keyword:" x)))
(define (##shape src x size)
(let ((n (##proper-length x)))
(if (or (##not n)
(if (##fixnum.< 0 size)
(##not (##fixnum.= n size))
(##fixnum.< n (##fixnum.- 0 size))))
(ct-error-syntax "Ill-formed special form:" (##car src)))))
(define (##proper-length l)
(define (len l n)
(cond ((##pair? l) (len (##cdr l) (##fixnum.+ n 1)))
((##null? l) n)
(else #f)))
(len l 0))
(define (##touch-list l)
(if-touches
(let loop ((l l))
(touch-vars (l)
(if (##pair? l)
(##cons (##car l) (loop (##cdr l)))
l)))
l))
(define (##read-expressions cte src filename)
(if (##string? filename)
(let ((port (##open-input-file filename)))
(define (read-exprs)
(let ((expr (##read port)))
(if (##not (##eof-object? expr))
(##cons expr (read-exprs))
'())))
(if port
(let ((exprs (read-exprs)))
(##close-port port)
exprs)
(ct-error-syntax "File not found")))
(ct-error-syntax "Filename expected")))
;------------------------------------------------------------------------------
; Compiler's main entry
(define (##compile src frames)
(let ((cte (##make-cte frames)) (tail? #t))
(gen ##gen-top
frames
(##comp-top (##cte-push-frame cte (##list (self-var))) src tail?))))
(define (##comp-top cte src tail?)
(let ((src (##touch-list src)))
(cond ((##symbol? src) (##comp-ref cte src tail?))
((##self-eval? src) (##comp-cst cte src tail?))
((##not (##pair? src)) (ct-error-syntax "Ill-formed expression"))
(else
(let ((first (##car src)))
(if (##macro? cte first)
(##comp-top cte (##macro-expand cte src) tail?)
(case first
((BEGIN) (##comp-top-BEGIN cte src tail?))
((DEFINE) (##comp-top-DEFINE cte src tail?))
((##DECLARE) (##comp-top-DECLARE cte src tail?))
((##DEFINE-MACRO) (##comp-top-DEFINE-MACRO cte src tail?))
((##INCLUDE) (##comp-top-INCLUDE cte src tail?))
(else (##comp-aux cte src tail? first)))))))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-top-BEGIN cte src tail?)
(##shape src src -1)
(##comp-top-seq cte src tail? (##cdr src)))
(define (##comp-top-seq cte src tail? seq)
(if (##pair? seq)
(##comp-top-seq-aux cte src tail? seq)
(gen ##gen-cst (unspecified-obj))))
(define (##comp-top-seq-aux cte src tail? seq)
(let ((rest (##cdr seq)))
(if (##pair? rest)
(gen ##gen-seq
(##comp-top cte (##car seq) #f)
(##comp-top-seq-aux cte src tail? rest))
(##comp-top cte (##car seq) tail?))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-top-DEFINE cte src tail?)
(let ((cte (##make-cte #f)))
(let ((name (##definition-name src)))
(let ((ind (##cte-lookup-var cte name)))
(gen ##gen-glo-def
name
ind
(##comp cte (##definition-value src) #f))))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-top-DECLARE cte src tail?)
(##shape src src -1)
(##cte-add-global-decl (##cdr src))
(gen ##gen-cst (unspecified-obj)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-top-DEFINE-MACRO cte src tail?)
(let ((name (##definition-name src)))
(##cte-add-global-macro name (##eval-global (##definition-value src)))
(gen ##gen-cst name)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-top-INCLUDE cte src tail?)
(##shape src src 2)
(##comp-top-seq cte src tail? (##read-expressions cte src (##cadr src))))
;------------------------------------------------------------------------------
(define (##comp cte src tail?)
(let ((src (##touch-list src)))
(cond ((##symbol? src) (##comp-ref cte src tail?))
((##self-eval? src) (##comp-cst cte src tail?))
((##not (##pair? src)) (ct-error-syntax "Ill-formed expression"))
(else
(let ((first (##car src)))
(if (##macro? cte first)
(##comp cte (##macro-expand cte src) tail?)
(case first
((BEGIN) (##comp-BEGIN cte src tail?))
((DEFINE) (ct-error-syntax "Ill-placed 'define'"))
((##DECLARE) (ct-error-syntax "Ill-placed '##declare'"))
((##DEFINE-MACRO) (ct-error-syntax "Ill-placed '##define-macro'"))
((##INCLUDE) (ct-error-syntax "Ill-placed '##include'"))
(else (##comp-aux cte src tail? first)))))))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-BEGIN cte src tail?)
(##shape src src -2)
(##comp-seq cte src tail? (##cdr src)))
(define (##comp-seq cte src tail? seq)
(if (##pair? seq)
(##comp-seq-aux cte src tail? seq)
(gen ##gen-cst (unspecified-obj))))
(define (##comp-seq-aux cte src tail? seq)
(let ((rest (##cdr seq)))
(if (##pair? rest)
(gen ##gen-seq
(##comp cte (##car seq) #f)
(##comp-seq-aux cte src tail? rest))
(##comp cte (##car seq) tail?))))
;------------------------------------------------------------------------------
(define (##comp-aux cte src tail? first)
(case first
((QUOTE) (##comp-QUOTE cte src tail?))
((QUASIQUOTE) (##comp-QUASIQUOTE cte src tail?))
((UNQUOTE) (ct-error-syntax "Ill-placed 'unquote'"))
((UNQUOTE-SPLICING) (ct-error-syntax "Ill-placed 'unquote-splicing'"))
((SET!) (##comp-SET! cte src tail?))
((LAMBDA) (##comp-LAMBDA cte src tail?))
((IF) (##comp-IF cte src tail?))
((COND) (##comp-COND cte src tail?))
((AND) (##comp-AND cte src tail?))
((OR) (##comp-OR cte src tail?))
((CASE) (##comp-CASE cte src tail?))
((LET) (##comp-LET cte src tail?))
((LET*) (##comp-LET* cte src tail?))
((LETREC) (##comp-LETREC cte src tail?))
((DO) (##comp-DO cte src tail?))
((DELAY) (##comp-DELAY cte src tail?))
((FUTURE) (##comp-FUTURE cte src tail?))
(else (##comp-app cte src tail?))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-ref cte src tail?)
(##variable src src)
(let ((x (##cte-lookup-var cte src)))
(if (loc-access? x)
(let ((up (loc-access-up x))
(over (loc-access-over x)))
(gen ##gen-loc-ref up over))
(gen ##gen-glo-ref x))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-cst cte src tail?)
(gen ##gen-cst src))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-QUOTE cte src tail?)
(##shape src src 2)
(gen ##gen-cst (##cadr src)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-QUASIQUOTE cte src tail?)
(##comp-quasi cte src tail? (##touch-list (##cadr src)) 1))
(define (##comp-quasi cte src tail? form level)
(cond ((##eq? level 0)
(##comp cte form tail?))
((##pair? form)
(let ((x (##car form)))
(touch-vars (x)
(case x
((QUASIQUOTE)
(##comp-quasi-list cte src tail? form (##fixnum.+ level 1)))
((UNQUOTE)
(if (##eq? level 1)
(##comp cte (##cadr form) tail?)
(##comp-quasi-list cte src tail? form (##fixnum.- level 1))))
((UNQUOTE-SPLICING)
(if (##eq? level 1)
(ct-error-syntax "Ill-placed 'unquote-splicing'"))
(##comp-quasi-list cte src tail? form (##fixnum.- level 1)))
(else
(##comp-quasi-list cte src tail? form level))))))
((##vector? form)
(gen ##gen-quasi-list->vector
(##comp-quasi-list cte src #f (##vector->list form) level)))
(else
(gen ##gen-cst form))))
(define (##comp-quasi-list cte src tail? l level)
(if (##pair? l)
(let ((first (##touch-list (##car l))))
(if (and (##eq? level 1) (##unquote-splicing? first))
(begin
(##shape src first 2)
(if (##null? (##cdr l))
(##comp cte (##cadr first) tail?)
(gen ##gen-quasi-append
(##comp cte (##cadr first) #f)
(##comp-quasi cte src #f (##cdr l) 1))))
(gen ##gen-quasi-cons
(##comp-quasi cte src #f first level)
(##comp-quasi cte src #f (##cdr l) level))))
(##comp-quasi cte src tail? l level)))
(define (##unquote-splicing? x)
(and (##pair? x)
(let ((y (##car x)))
(touch-vars (y)
(##eq? y 'UNQUOTE-SPLICING)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-SET! cte src tail?)
(##shape src src 3)
(let ((var (##cadr src)))
(touch-vars (var)
(begin
(##variable src var)
(let ((x (##cte-lookup-var cte var)))
(if (loc-access? x)
(let ((up (loc-access-up x))
(over (loc-access-over x)))
(gen ##gen-loc-set up over (##comp cte (##caddr src) #f)))
(gen ##gen-glo-set x (##comp cte (##caddr src) #f))))))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-LAMBDA cte src tail?)
(##shape src src -3)
(##comp-lambda-aux cte src tail? (##touch-list (##cadr src)) (##cddr src)))
(define (##comp-lambda-aux cte src tail? parms body)
(let ((frame (##parms->frame src parms)))
(let ((c (##comp-body (##cte-push-frame cte (##cons (self-var) frame)) src #t body)))
(if (##rest-param? parms)
(gen ##gen-prc-rest frame c)
(gen ##gen-prc frame c)))))
(define (##parms->frame src parms)
(cond ((##null? parms)
'())
((##pair? parms)
(let ((x (##car parms)))
(touch-vars (x)
(let ((rest (##parms->frame src (##cdr parms))))
(##variable src x)
(if (##memq x rest)
(ct-error-syntax "Duplicate parameter in parameter list"))
(##cons x rest)))))
(else
(##variable src parms)
(##list parms))))
(define (##rest-param? parms)
(cond ((##pair? parms)
(##rest-param? (##cdr parms)))
((##null? parms)
#f)
(else
#t)))
(define (##comp-body cte src tail? body)
(define (letrec-defines cte vars vals body)
(if (##pair? body)
(let ((src (##touch-list (##car body))))
(if (##not (##pair? src))
(letrec-defines* cte vars vals body)
(let ((first (##car src)))
(touch-vars (first)
(if (##macro? cte first)
(letrec-defines cte
vars
vals
(##cons (##macro-expand cte src) (##cdr body)))
(case first
((BEGIN)
(letrec-defines cte
vars
vals
(##append (##cdr src) (##cdr body))))
((DEFINE)
(let ((x (##definition-name src)))
(##variable src x)
(if (##memq x vars)
(ct-error-syntax "Duplicate definition of a variable"))
(letrec-defines cte
(##cons x vars)
(##cons (##definition-value src) vals)
(##cdr body))))
((##DECLARE)
(##shape src src -1)
(letrec-defines (##cte-push-decl cte (##cdr src))
vars
vals
(##cdr body)))
((##DEFINE-MACRO)
(let ((x (##definition-name src)))
(letrec-defines (##cte-push-macro
cte
x
(##eval-global (##definition-value src)))
vars
vals
(##cdr body))))
((##INCLUDE)
(##shape src src 2)
(letrec-defines cte
vars
vals
(##append (##read-expressions cte src (##cadr src))
(##cdr body))))
(else
(letrec-defines* cte vars vals body))))))))
(ct-error-syntax "Body must contain at least one evaluable expression")))
(define (letrec-defines* cte vars vals body)
(if (##null? vars)
(##comp-seq cte src tail? body)
(##comp-letrec-aux cte src tail? vars vals body)))
(letrec-defines cte '() '() body))
(define (##definition-name src)
(##shape src src -3)
(let ((pattern (##cadr src)))
(touch-vars (pattern)
(let ((name (if (##pair? pattern)
(let ((name (##car pattern)))
(touch-vars (name)
name))
(begin
(##shape src src 3)
pattern))))
(if (##not (##symbol? name))
(ct-error-syntax "Defined variable must be an identifier"))
name))))
(define (##definition-value src)
(let ((pattern (##cadr src)))
(touch-vars (pattern)
(if (##pair? pattern)
(##cons 'LAMBDA (##cons (##cdr pattern) (##cddr src)))
(##caddr src)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-IF cte src tail?)
(##shape src src -3)
(if (##pair? (##cdddr src))
(begin
(##shape src src 4)
(gen ##gen-if3
(##comp cte (##cadr src) #f)
(##comp cte (##caddr src) tail?)
(##comp cte (##cadddr src) tail?)))
(begin
(##shape src src 3)
(gen ##gen-if2
(##comp cte (##cadr src) #f)
(##comp cte (##caddr src) tail?)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-COND cte src tail?)
(##shape src src -2)
(##comp-cond-aux cte src tail? (##cdr src)))
(define (##comp-cond-aux cte src tail? clauses)
(if (##pair? clauses)
(let ((clause (##touch-list (##car clauses))))
(##shape src clause -1)
(let ((x (##car clause)))
(touch-vars (x)
(cond ((##eq? x 'ELSE)
(##shape src clause -2)
(if (##not (##null? (##cdr clauses)))
(ct-error-syntax "ELSE clause must be last"))
(##comp-seq cte src tail? (##cdr clause)))
((##not (##pair? (##cdr clause)))
(gen ##gen-cond-or
(##comp cte (##car clause) #f)
(##comp-cond-aux cte src tail? (##cdr clauses))))
(else
(let ((y (##cadr clause)))
(touch-vars (y)
(if (##eq? y '=>)
(begin
(##shape src clause -3)
(gen ##gen-cond-send
(##comp cte (##car clause) #f)
(##comp cte (##caddr clause) #f)
(##comp-cond-aux cte src tail? (##cdr clauses))))
(gen ##gen-cond-if
(##comp cte (##car clause) #f)
(##comp-seq cte src tail? (##cdr clause))
(##comp-cond-aux cte src tail? (##cdr clauses)))))))))))
(gen ##gen-cst (unspecified-obj))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-AND cte src tail?)
(let ((rest (##cdr src)))
(if (##pair? rest)
(##comp-and-aux cte src tail? rest)
(gen ##gen-cst #t))))
(define (##comp-and-aux cte src tail? l)
(let ((rest (##cdr l)))
(if (##pair? rest)
(gen ##gen-and
(##comp cte (##car l) #f)
(##comp-and-aux cte src tail? rest))
(##comp cte (##car l) tail?))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-OR cte src tail?)
(let ((rest (##cdr src)))
(if (##pair? rest)
(##comp-or-aux cte src tail? rest)
(gen ##gen-cst #f))))
(define (##comp-or-aux cte src tail? l)
(let ((rest (##cdr l)))
(if (##pair? rest)
(gen ##gen-or
(##comp cte (##car l) #f)
(##comp-or-aux cte src tail? rest))
(##comp cte (##car l) tail?))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-CASE cte src tail?)
(##shape src src -3)
(gen ##gen-case
(##comp cte (##cadr src) #f)
(let ((cte (##cte-push-frame cte (##list (selector-var)))))
(##comp-case-aux cte src tail? (##cddr src)))))
(define (##comp-case-aux cte src tail? clauses)
(if (##pair? clauses)
(let ((clause (##touch-list (##car clauses))))
(##shape src clause -2)
(let ((first (##touch-list (##car clause))))
(if (##eq? first 'ELSE)
(begin
(if (##not (##null? (##cdr clauses)))
(ct-error-syntax "ELSE clause must be last"))
(gen ##gen-case-else
(##comp-seq cte src tail? (##cdr clause))))
(gen ##gen-case-clause
first
(##comp-seq cte src tail? (##cdr clause))
(##comp-case-aux cte src tail? (##cdr clauses))))))
(gen ##gen-case-else
(gen ##gen-cst (unspecified-obj)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-LET cte src tail?)
(##shape src src -3)
(let ((x (##touch-list (##cadr src))))
(cond ((##symbol? x)
(##shape src src -4)
(let ((bindings (##touch-list (##caddr src))))
(let* ((vars (##bindings->vars src bindings #t))
(vals (##bindings->vals bindings)))
(gen ##gen-app
(let ((inner-cte (##cte-push-frame cte (##list x))))
(gen ##gen-letrec
(##list x)
(let ((cte inner-cte)
(tail? #f))
(##list (gen ##gen-prc
vars
(##comp-body (##cte-push-frame cte (##cons (self-var) vars))
src
#t
(##cdddr src)))))
(let ((cte inner-cte)
(tail? #f))
(gen ##gen-loc-ref 0 1)))) ; fetch loop variable
(##comp-vals cte vals)))))
((##null? x)
(##comp-body cte src tail? (##cddr src)))
(else
(let* ((bindings x)
(vars (##bindings->vars src bindings #t))
(vals (##bindings->vals bindings)))
(let ((c (##comp-body (##cte-push-frame cte vars) src tail? (##cddr src))))
(gen ##gen-let
vars
(##comp-vals cte vals)
c)))))))
(define (##comp-vals cte l)
(if (##pair? l)
(##cons (##comp cte (##car l) #f) (##comp-vals cte (##cdr l)))
'()))
(define (##bindings->vars src bindings check-duplicates?)
(if (##pair? bindings)
(let ((binding (##touch-list (##car bindings))))
(##shape src binding 2)
(let ((x (##car binding)))
(touch-vars (x)
(let ((rest (##bindings->vars src (##cdr bindings) check-duplicates?)))
(##variable src x)
(if (and check-duplicates? (##memq x rest))
(ct-error-syntax "Duplicate variable in bindings"))
(##cons x rest)))))
(if (##null? bindings)
'()
(ct-error-syntax "Ill-terminated bindings"))))
(define (##bindings->vals bindings)
(if (##pair? bindings)
(let ((binding (##touch-list (##car bindings))))
(##cons (##cadr binding) (##bindings->vals (##cdr bindings))))
'()))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-LET* cte src tail?)
(##shape src src -3)
(let ((bindings (##cadr src)))
(touch-vars (bindings)
(let* ((vars (##bindings->vars src bindings #f))
(vals (##bindings->vals bindings)))
(##comp-let*-aux cte src tail? vars vals (##cddr src))))))
(define (##comp-let*-aux cte src tail? vars vals body)
(if (##pair? vars)
(let ((frame (##list (##car vars))))
(let ((inner-cte (##cte-push-frame cte frame)))
(gen ##gen-let
frame
(##list (##comp cte (##car vals) #f))
(##comp-let*-aux inner-cte src tail? (##cdr vars) (##cdr vals) body))))
(##comp-body cte src tail? body)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-LETREC cte src tail?)
(##shape src src -3)
(let ((bindings (##touch-list (##cadr src))))
(if (##null? bindings)
(##comp-body cte src tail? (##cddr src))
(let* ((vars (##bindings->vars src bindings #t))
(vals (##bindings->vals bindings)))
(##comp-letrec-aux cte src tail? vars vals (##cddr src))))))
(define (##comp-letrec-aux cte src tail? vars vals body)
(if (##pair? vars)
(let ((inner-cte (##cte-push-frame cte vars)))
(gen ##gen-letrec
vars
(##comp-vals inner-cte vals)
(##comp-body inner-cte src tail? body)))
(##comp-body cte src tail? body)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-do cte src tail?)
(##shape src src -3)
(let ((bindings (##touch-list (##cadr src)))
(exit (##touch-list (##caddr src))))
(##shape src exit -1)
(let* ((vars (##bindings->vars* src bindings))
(do-loop-vars (##list (do-loop-var)))
(inner-cte (##cte-push-frame cte do-loop-vars)))
(gen ##gen-letrec
do-loop-vars
(##list
(let ((cte inner-cte)
(tail? #f))
(gen ##gen-prc
vars
(let ((cte (##cte-push-frame cte (##cons (self-var) vars)))
(tail? #t))
(gen ##gen-if3
(##comp cte (##car exit) #f)
(##comp-seq cte src tail? (##cdr exit))
(let ((call
(gen ##gen-app
(let ((tail? #f))
(gen ##gen-loc-ref 1 1)) ; fetch do-loop-var
(##comp-vals cte (##bindings->steps bindings)))))
(if (##null? (##cdddr src))
call
(gen ##gen-seq
(##comp-seq cte src #f (##cdddr src))
call))))))))
(let ((cte inner-cte))
(gen ##gen-app
(let ((tail? #f))
(gen ##gen-loc-ref 0 1)) ; fetch do-loop-var
(##comp-vals cte (##bindings->vals bindings))))))))
(define (##bindings->vars* src bindings)
(if (##pair? bindings)
(let ((binding (##touch-list (##car bindings))))
(##shape src binding -2)
(if (##pair? (##cddr binding)) (##shape src binding 3))
(let ((x (##car binding)))
(touch-vars (x)
(let ((rest (##bindings->vars* src (##cdr bindings))))
(##variable src x)
(if (##memq x rest)
(ct-error-syntax "Duplicate variable in bindings"))
(##cons x rest)))))
(if (##null? bindings)
'()
(ct-error-syntax "Ill-terminated bindings"))))
(define (##bindings->steps bindings)
(if (##pair? bindings)
(let ((binding (##touch-list (##car bindings))))
(##cons (if (##pair? (##cddr binding)) (##caddr binding) (##car binding))
(##bindings->steps (##cdr bindings))))
'()))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-app cte src tail?)
(let ((n (##proper-length src)))
(if n
(gen ##gen-app
(##comp cte (##car src) #f)
(##comp-vals cte (##cdr src)))
(ct-error-syntax "Ill-formed procedure application"))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-DELAY cte src tail?)
(##shape src src 2)
(gen ##gen-delay (##comp cte (##cadr src) #t)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##comp-FUTURE cte src tail?)
(##shape src src 2)
(gen ##gen-future (##comp cte (##cadr src) #t)))
;==============================================================================
; Code generation procedures
;------------------------------------------------------------------------------
; Macros to manipulate the runtime environment
(##define-macro (mk-rte rte . lst)
(let ((n (length lst)))
`(let (($rte (##make-vector ,(+ n 1) (unspecified-obj))))
(##vector-set! $rte 0 ,rte)
,@(let loop2 ((l lst) (i 1) (r '()))
(if (pair? l)
(loop2 (cdr l) (+ i 1) (cons `(##vector-set! $rte ,i ,(car l)) r))
(reverse r)))
$rte)))
(##define-macro (mk-rte* rte n)
`(let (($rte (##make-vector (##fixnum.+ ,n 1) (unspecified-obj))))
(##vector-set! $rte 0 ,rte)
$rte))
(##define-macro (rte-up rte) `(##vector-ref ,rte 0))
(##define-macro (rte-ref rte i) `(##vector-ref ,rte ,i))
(##define-macro (rte-set! rte i val) `(##vector-set! ,rte ,i ,val))
;------------------------------------------------------------------------------
(define ##cprc-top
(mk-cprc
(##subproblem-apply0 $code rte
(lambda ()
(let ((rte (mk-rte rte #f)))
(code-run (^ 0)))))))
(define ##gen-top
(mk-gen (frames val)
(mk-code ##cprc-top (val) frames)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-cst-null (mk-cprc '()))
(define ##cprc-cst-true (mk-cprc #t))
(define ##cprc-cst-false (mk-cprc #f))
(define ##cprc-cst--2 (mk-cprc -2))
(define ##cprc-cst--1 (mk-cprc -1))
(define ##cprc-cst-0 (mk-cprc 0))
(define ##cprc-cst-1 (mk-cprc 1))
(define ##cprc-cst-2 (mk-cprc 2))
(define ##cprc-cst (mk-cprc (^ 0)))
(define ##gen-cst
(mk-gen (val)
(case val
((()) (mk-code ##cprc-cst-null ()))
((#t) (mk-code ##cprc-cst-true ()))
((#f) (mk-code ##cprc-cst-false ()))
((-2) (mk-code ##cprc-cst--2 ()))
((-1) (mk-code ##cprc-cst--1 ()))
((0) (mk-code ##cprc-cst-0 ()))
((1) (mk-code ##cprc-cst-1 ()))
((2) (mk-code ##cprc-cst-2 ()))
(else (mk-code ##cprc-cst () val)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-loc-ref-0-1 (mk-cprc (rte-ref rte 1)))
(define ##cprc-loc-ref-0-2 (mk-cprc (rte-ref rte 2)))
(define ##cprc-loc-ref-0-3 (mk-cprc (rte-ref rte 3)))
(define ##cprc-loc-ref-1-1 (mk-cprc (rte-ref (rte-up rte) 1)))
(define ##cprc-loc-ref-1-2 (mk-cprc (rte-ref (rte-up rte) 2)))
(define ##cprc-loc-ref-1-3 (mk-cprc (rte-ref (rte-up rte) 3)))
(define ##cprc-loc-ref-2-1 (mk-cprc (rte-ref (rte-up (rte-up rte)) 1)))
(define ##cprc-loc-ref-2-2 (mk-cprc (rte-ref (rte-up (rte-up rte)) 2)))
(define ##cprc-loc-ref-2-3 (mk-cprc (rte-ref (rte-up (rte-up rte)) 3)))
(define ##cprc-loc-ref
(mk-cprc
(let loop ((e rte) (i (^ 0)))
(if (##fixnum.< 0 i)
(loop (rte-up e) (##fixnum.- i 1))
(rte-ref e (^ 1))))))
(define ##gen-loc-ref
(mk-gen (up over)
(case up
((0)
(case over
((1) (mk-code ##cprc-loc-ref-0-1 ()))
((2) (mk-code ##cprc-loc-ref-0-2 ()))
((3) (mk-code ##cprc-loc-ref-0-3 ()))
(else (mk-code ##cprc-loc-ref () up over))))
((1)
(case over
((1) (mk-code ##cprc-loc-ref-1-1 ()))
((2) (mk-code ##cprc-loc-ref-1-2 ()))
((3) (mk-code ##cprc-loc-ref-1-3 ()))
(else (mk-code ##cprc-loc-ref () up over))))
((2)
(case over
((1) (mk-code ##cprc-loc-ref-2-1 ()))
((2) (mk-code ##cprc-loc-ref-2-2 ()))
((3) (mk-code ##cprc-loc-ref-2-3 ()))
(else (mk-code ##cprc-loc-ref () up over))))
(else
(mk-code ##cprc-loc-ref () up over)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-glo-ref
(mk-cprc
(let loop ((val (global-env-ref (^ 0))))
(if (unbound? val)
(loop (rt-error-unbound-global-var $code rte))
val))))
(define ##gen-glo-ref
(mk-gen (ind)
(mk-code ##cprc-glo-ref () ind)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-loc-set
(mk-cprc
(let ((val (code-run (^ 0))))
(let loop ((e rte) (i (^ 1)))
(if (##fixnum.< 0 i)
(loop (rte-up e) (##fixnum.- i 1))
(begin
(rte-set! e (^ 2) val)
(set!-ret-obj)))))))
(define ##gen-loc-set
(mk-gen (up over val)
(mk-code ##cprc-loc-set (val) up over)))
(define ##cprc-glo-set
(mk-cprc
(let ((val (code-run (^ 0))))
(global-env-set! (^ 1) val)
(set!-ret-obj))))
(define ##gen-glo-set
(mk-gen (ind val)
(mk-code ##cprc-glo-set (val) ind)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-glo-def
(mk-cprc
(let ((rte #f))
(global-env-set! (^ 1) (code-run (^ 0)))
(^ 2))))
(define ##gen-glo-def
(mk-gen (name ind val)
(mk-code ##cprc-glo-def (val) ind name)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-if2
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
(code-run (^ 1))
(unspecified-obj))))))
(define ##gen-if2
(mk-gen (pre con)
(mk-code ##cprc-if2 (pre con))))
(define ##cprc-if3
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
(code-run (^ 1))
(code-run (^ 2)))))))
(define ##gen-if3
(mk-gen (pre con alt)
(mk-code ##cprc-if3 (pre con alt))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-seq
(mk-cprc
(code-run (^ 0))
(code-run (^ 1))))
(define ##gen-seq
(mk-gen (val1 val2)
(mk-code ##cprc-seq (val1 val2))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-quasi-list->vector
(mk-cprc
(quasi-list->vector (code-run (^ 0)))))
(define ##gen-quasi-list->vector
(mk-gen (val)
(mk-code ##cprc-quasi-list->vector (val))))
(define ##cprc-quasi-append
(mk-cprc
(quasi-append (code-run (^ 0)) (code-run (^ 1)))))
(define ##gen-quasi-append
(mk-gen (val1 val2)
(mk-code ##cprc-quasi-append (val1 val2))))
(define ##cprc-quasi-cons
(mk-cprc
(quasi-cons (code-run (^ 0)) (code-run (^ 1)))))
(define ##gen-quasi-cons
(mk-gen (val1 val2)
(mk-code ##cprc-quasi-cons (val1 val2))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-cond-if
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
(code-run (^ 1))
(code-run (^ 2)))))))
(define ##gen-cond-if
(mk-gen (val1 val2 val3)
(mk-code ##cprc-cond-if (val1 val2 val3))))
(define ##cprc-cond-or
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
pred
(code-run (^ 1)))))))
(define ##gen-cond-or
(mk-gen (val1 val2)
(mk-code ##cprc-cond-or (val1 val2))))
(define ##cprc-cond-send-red
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
(let loop ((proc (code-run (^ 1))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(loop (rt-error-non-procedure-send $code rte))
(##reduction-apply1 $code rte proc pred))))
(code-run (^ 2)))))))
(define ##cprc-cond-send-sub
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
(let loop ((proc (code-run (^ 1))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(loop (rt-error-non-procedure-send $code rte))
(##subproblem-apply1 $code rte proc pred))))
(code-run (^ 2)))))))
(define ##gen-cond-send
(mk-gen (val1 val2 val3)
(mk-code (if tail? ##cprc-cond-send-red ##cprc-cond-send-sub)
(val1 val2 val3))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-or
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (true? pred)
pred
(code-run (^ 1)))))))
(define ##gen-or
(mk-gen (val1 val2)
(mk-code ##cprc-or (val1 val2))))
(define ##cprc-and
(mk-cprc
(let ((pred (code-run (^ 0))))
(touch-vars (pred)
(if (##not (true? pred))
pred
(code-run (^ 1)))))))
(define ##gen-and
(mk-gen (val1 val2)
(mk-code ##cprc-and (val1 val2))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-case
(mk-cprc
(let ((selector (code-run (^ 0))))
(touch-vars (selector)
(let ((rte (mk-rte rte selector)))
(code-run (^ 1)))))))
(define ##gen-case
(mk-gen (val1 val2)
(mk-code ##cprc-case (val1 val2))))
(define ##cprc-case-clause
(mk-cprc
(if (##case-memv (rte-ref rte 1) (^ 2))
(code-run (^ 0))
(code-run (^ 1)))))
(define ##gen-case-clause
(mk-gen (cases val1 val2)
(mk-code ##cprc-case-clause (val1 val2) cases)))
(define ##cprc-case-else
(mk-cprc
(code-run (^ 0))))
(define ##gen-case-else
(mk-gen (val)
(mk-code ##cprc-case-else (val))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-let
(mk-cprc
(let ((n (##fixnum.- (code-length $code) 2)))
(let ((inner-rte (mk-rte* rte n)))
(let loop ((i n))
(if (##fixnum.< 0 i)
(begin
(rte-set! inner-rte i (code-run (code-ref $code i)))
(loop (##fixnum.- i 1)))
(let ((rte inner-rte))
(code-run (^ 0)))))))))
(define ##gen-let
(mk-gen (vars vals body)
(let ((c (##mk-code* ##cprc-let (##cons body vals) 1)))
(code-set! c (##fixnum.+ (##length vals) 1) vars)
c)))
(define ##cprc-letrec
(mk-cprc
(let ((n (##fixnum.- (code-length $code) 2)))
(let ((rte (mk-rte* rte n)))
(let loop ((i n))
(if (##fixnum.< 0 i)
(begin
(rte-set! rte i (code-run (code-ref $code i)))
(loop (##fixnum.- i 1)))
(code-run (^ 0))))))))
(define ##gen-letrec
(mk-gen (vars vals body)
(let ((c (##mk-code* ##cprc-letrec (##cons body vals) 1)))
(code-set! c (##fixnum.+ (##length vals) 1) vars)
c)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-prc0
(mk-cprc
(letrec ((proc
(lambda ()
(let ((rte (mk-rte rte proc)))
(code-run (^ 0))))))
proc)))
(define ##cprc-prc1
(mk-cprc
(letrec ((proc
(lambda (arg1)
(let ((rte (mk-rte rte proc arg1)))
(code-run (^ 0))))))
proc)))
(define ##cprc-prc2
(mk-cprc
(letrec ((proc
(lambda (arg1 arg2)
(let ((rte (mk-rte rte proc arg1 arg2)))
(code-run (^ 0))))))
proc)))
(define ##cprc-prc3
(mk-cprc
(letrec ((proc
(lambda (arg1 arg2 arg3)
(let ((rte (mk-rte rte proc arg1 arg2 arg3)))
(code-run (^ 0))))))
proc)))
(define ##cprc-prc
(mk-cprc
(letrec ((proc
(lambda args
(let ((n (^ 1)))
(let ((inner-rte (mk-rte* rte n)))
(rte-set! inner-rte 1 proc)
(let loop ((i 2) (l args))
(if (##fixnum.< n i)
(if (##pair? l)
(rt-error-too-many-args proc args)
(let ((rte inner-rte))
(code-run (^ 0))))
(if (##pair? l)
(begin
(rte-set! inner-rte i (##car l))
(loop (##fixnum.+ i 1) (##cdr l)))
(rt-error-too-few-args proc args)))))))))
proc)))
(define ##gen-prc
(mk-gen (frame body)
(case (##length frame)
((0) (mk-code ##cprc-prc0 (body) frame))
((1) (mk-code ##cprc-prc1 (body) frame))
((2) (mk-code ##cprc-prc2 (body) frame))
((3) (mk-code ##cprc-prc3 (body) frame))
(else (mk-code ##cprc-prc (body) (##fixnum.+ (##length frame) 1) frame)))))
(define ##cprc-prc-rest
(mk-cprc
(letrec ((proc
(lambda args
(let ((n (^ 1)))
(let ((inner-rte (mk-rte* rte n)))
(rte-set! inner-rte 1 proc)
(let loop ((i 2) (l args))
(if (##fixnum.< i n)
(if (##pair? l)
(begin
(rte-set! inner-rte i (##car l))
(loop (##fixnum.+ i 1) (##cdr l)))
(rt-error-too-few-args proc args))
(begin
(rte-set! inner-rte i l)
(let ((rte inner-rte))
(code-run (^ 0)))))))))))
proc)))
(define ##gen-prc-rest
(mk-gen (frame body)
(mk-code ##cprc-prc-rest (body) (##fixnum.+ (##length frame) 1) frame)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-app0-red
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(##reduction-apply0 $code rte proc))))))
(define ##cprc-app1-red
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let ((arg1 (code-run (^ 1))))
(##reduction-apply1 $code rte proc arg1)))))))
(define ##cprc-app2-red
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let ((arg1 (code-run (^ 1)))
(arg2 (code-run (^ 2))))
(##reduction-apply2 $code rte proc arg1 arg2)))))))
(define ##cprc-app3-red
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let ((arg1 (code-run (^ 1)))
(arg2 (code-run (^ 2)))
(arg3 (code-run (^ 3))))
(##reduction-apply3 $code rte proc arg1 arg2 arg3)))))))
(define ##cprc-app-red
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let loop ((i (##fixnum.- (code-length $code) 1)) (args '()))
(if (##fixnum.< 0 i)
(loop (##fixnum.- i 1) (##cons (code-run (code-ref $code i)) args))
(##reduction-apply $code rte proc args))))))))
(define ##cprc-app0-sub
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(##subproblem-apply0 $code rte proc))))))
(define ##cprc-app1-sub
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let ((arg1 (code-run (^ 1))))
(##subproblem-apply1 $code rte proc arg1)))))))
(define ##cprc-app2-sub
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let ((arg1 (code-run (^ 1)))
(arg2 (code-run (^ 2))))
(##subproblem-apply2 $code rte proc arg1 arg2)))))))
(define ##cprc-app3-sub
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let ((arg1 (code-run (^ 1)))
(arg2 (code-run (^ 2)))
(arg3 (code-run (^ 3))))
(##subproblem-apply3 $code rte proc arg1 arg2 arg3)))))))
(define ##cprc-app-sub
(mk-cprc
(let ((proc (code-run (^ 0))))
(touch-vars (proc)
(if (##not (##procedure? proc))
(rt-error-non-procedure-oper $code rte)
(let loop ((i (##fixnum.- (code-length $code) 1)) (args '()))
(if (##fixnum.< 0 i)
(loop (##fixnum.- i 1) (##cons (code-run (code-ref $code i)) args))
(##subproblem-apply $code rte proc args))))))))
(define ##gen-app
(mk-gen (oper args)
(case (##length args)
((0) (mk-code (if tail? ##cprc-app0-red ##cprc-app0-sub) (oper)))
((1) (mk-code (if tail? ##cprc-app1-red ##cprc-app1-sub) (oper (##car args))))
((2) (mk-code (if tail? ##cprc-app2-red ##cprc-app2-sub) (oper (##car args) (##cadr args))))
((3) (mk-code (if tail? ##cprc-app3-red ##cprc-app3-sub) (oper (##car args) (##cadr args) (##caddr args))))
(else (##mk-code* (if tail? ##cprc-app-red ##cprc-app-sub) (##cons oper args) 0)))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##reduction-apply0 $code rte proc)
(##declare (intr-checks))
(proc))
(define (##reduction-apply1 $code rte proc arg1)
(##declare (intr-checks))
(proc arg1))
(define (##reduction-apply2 $code rte proc arg1 arg2)
(##declare (intr-checks))
(proc arg1 arg2))
(define (##reduction-apply3 $code rte proc arg1 arg2 arg3)
(##declare (intr-checks))
(proc arg1 arg2 arg3))
(define (##reduction-apply $code rte proc args)
(##declare (intr-checks))
(##apply proc args))
(define (##subproblem-apply0 $code rte proc)
(##declare (intr-checks))
(let ((result (proc)))
(let ((a $code) (b rte))
result)))
(define (##subproblem-apply1 $code rte proc arg1)
(##declare (intr-checks))
(let ((result (proc arg1)))
(let ((a $code) (b rte))
result)))
(define (##subproblem-apply2 $code rte proc arg1 arg2)
(##declare (intr-checks))
(let ((result (proc arg1 arg2)))
(let ((a $code) (b rte))
result)))
(define (##subproblem-apply3 $code rte proc arg1 arg2 arg3)
(##declare (intr-checks))
(let ((result (proc arg1 arg2 arg3)))
(let ((a $code) (b rte))
result)))
(define (##subproblem-apply $code rte proc args)
(##declare (intr-checks))
(let ((result (##apply proc args)))
(let ((a $code) (b rte))
result)))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-delay
(mk-cprc
(delay (code-run (^ 0)))))
(define ##gen-delay
(mk-gen (val)
(mk-code ##cprc-delay (val))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##cprc-future
(mk-cprc
(future (code-run (^ 0)))))
(define ##gen-future
(mk-gen (val)
(mk-code ##cprc-future (val))))
;------------------------------------------------------------------------------
; Access to compiler created structures for interpreter procedures and frames
(define ##int-proc-body-format-1
(##list (##proc-closure-body (##cprc-prc0 #f #f))
(##proc-closure-body (##cprc-prc1 #f #f))
(##proc-closure-body (##cprc-prc2 #f #f))
(##proc-closure-body (##cprc-prc3 #f #f))))
(define ##int-proc-body-format-2
(##list (##proc-closure-body (##cprc-prc #f #f))
(##proc-closure-body (##cprc-prc-rest #f #f))))
(define (##int-proc? x)
(and (##procedure? x)
(##proc-closure? x)
(or (##memq (##proc-closure-body x) ##int-proc-body-format-1)
(##memq (##proc-closure-body x) ##int-proc-body-format-2))))
(define (##int-proc-code x)
(if (##memq (##proc-closure-body x) ##int-proc-body-format-1)
(##proc-closure-ref x 0)
(##proc-closure-ref x 2)))
(define (##int-proc-rte x)
(if (##memq (##proc-closure-body x) ##int-proc-body-format-1)
(##proc-closure-ref x 2)
(##proc-closure-ref x 1)))
;==============================================================================
; Eval
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Evaluation in the global environment (with current dynamic env)
(define ##eval-global #f)
(set! ##eval-global
(lambda (expr)
(##eval expr #f #f (##dynamic-env-ref))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Evaluation in a particular environment ('frames' describes the runtime
; environment 'rte').
(define ##eval #f)
(set! ##eval
(lambda (expr frames rte dyn-env)
(let ((c (##compile expr frames)))
(##dynamic-env-bind
dyn-env
(lambda () (let ((rte rte)) (code-run c)))))))
;==============================================================================
; Decompilation of a piece of code
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(##define-macro (mk-degen params . def)
`(lambda ($code ,@params) ,@def))
(##define-macro (degen proc . args)
`(,proc $code ,@args))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##extract-frame subcode up)
(let (($code (code-link subcode)))
(if $code
(let ((cprc (code-cprc $code)))
(cond ((##eq? cprc ##cprc-top)
(##extract-frame-top $code subcode up))
((##eq? cprc ##cprc-glo-def)
(##extract-frame-glo-def $code subcode up))
((##eq? cprc ##cprc-case)
(##extract-frame-case $code subcode up))
((##eq? cprc ##cprc-let)
(##extract-frame-let $code subcode up))
((##eq? cprc ##cprc-letrec)
(##extract-frame-letrec $code subcode up))
((or (##eq? cprc ##cprc-prc0)
(##eq? cprc ##cprc-prc1)
(##eq? cprc ##cprc-prc2)
(##eq? cprc ##cprc-prc3)
(##eq? cprc ##cprc-prc)
(##eq? cprc ##cprc-prc-rest))
(##extract-frame-prc $code subcode up))
(else
(##extract-frame-default $code subcode up))))
#f)))
(define ##extract-frame-default
(lambda ($code subcode up)
(##extract-frame $code up)))
(define ##extract-frame-top
(lambda ($code subcode up)
(if (##fixnum.= up 0)
(##list (self-var))
(let loop ((frames (^ 1)) (up (##fixnum.- up 1)))
(if frames
(if (##fixnum.= up 0)
(##car frames)
(loop (##cdr frames) (##fixnum.- up 1)))
#f)))))
(define ##extract-frame-glo-def
(lambda ($code subcode up)
#f))
(define ##extract-frame-case
(lambda ($code subcode up)
(if (##eq? subcode (^ 1))
(if (##fixnum.= up 0)
(##list (selector-var))
(##extract-frame $code (##fixnum.- up 1)))
(##extract-frame $code up))))
(define ##extract-frame-let
(lambda ($code subcode up)
(if (##eq? subcode (^ 0))
(if (##fixnum.= up 0)
(code-ref $code (##fixnum.- (code-length $code) 1))
(##extract-frame $code (##fixnum.- up 1)))
(##extract-frame $code up))))
(define ##extract-frame-letrec
(lambda ($code subcode up)
(if (##fixnum.= up 0)
(code-ref $code (##fixnum.- (code-length $code) 1))
(##extract-frame $code (##fixnum.- up 1)))))
(define ##extract-frame-prc
(lambda ($code subcode up)
(if (##fixnum.= up 0)
(##cons (self-var) (code-ref $code (##fixnum.- (code-length $code) 1)))
(##extract-frame $code (##fixnum.- up 1)))))
(define (##extract-frames $code)
(define (rev l tail)
(if (##pair? l) (rev (##cdr l) (##cons (##car l) tail)) tail))
(let loop ((i 0) (frames '()))
(let ((frame (##extract-frame $code i)))
(if frame
(loop (##fixnum.+ i 1) (##cons frame frames))
(rev frames #f)))))
(define (##extract-proc $code rte)
(let loop ((i 0) (rte rte))
(let ((frame (##extract-frame $code i)))
(if frame
(if (and (##pair? frame) (##eq? (##car frame) (self-var)))
(rte-ref rte 1)
(loop (##fixnum.+ i 1) (rte-up rte)))
#f))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##BEGIN? x) (and (##pair? x) (##eq? (##car x) 'BEGIN)))
(define (##COND? x) (and (##pair? x) (##eq? (##car x) 'COND)))
(define (##AND? x) (and (##pair? x) (##eq? (##car x) 'AND)))
(define (##OR? x) (and (##pair? x) (##eq? (##car x) 'OR)))
(define (##unspecified-obj? x)
(and (##pair? x) (##eq? (##car x) 'QUOTE) (##eq? (##cadr x) (unspecified-obj))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define ##degen-top
(mk-degen ()
(##decomp (^ 0))))
(define ##degen-cst-x
(mk-degen (val)
(if (##self-eval? val) val (##list 'QUOTE val))))
(define ##degen-cst
(mk-degen ()
(degen ##degen-cst-x (^ 0))))
(define ##degen-loc-ref-x-y
(mk-degen (up over)
(degen ##degen-up-over up over)))
(define ##degen-up-over
(mk-degen (up over)
(let loop ((l (##extract-frame $code up)) (i over))
(if (##fixnum.< i 2)
(##car l)
(loop (##cdr l) (##fixnum.- i 1))))))
(define ##degen-loc-ref
(mk-degen ()
(degen ##degen-loc-ref-x-y (^ 0) (^ 1))))
(define ##degen-glo-ref
(mk-degen ()
(global-env-loc->var (^ 0))))
(define ##degen-loc-set
(mk-degen ()
(##list 'SET! (degen ##degen-up-over (^ 1) (^ 2))
(##decomp (^ 0)))))
(define ##degen-glo-set
(mk-degen ()
(##list 'SET! (global-env-loc->var (^ 1))
(##decomp (^ 0)))))
(define ##degen-glo-def
(mk-degen ()
(##list 'DEFINE (global-env-loc->var (^ 1))
(##decomp (^ 0)))))
(define ##degen-if2
(mk-degen ()
(##list 'IF (##decomp (^ 0))
(##decomp (^ 1)))))
(define ##degen-if3
(mk-degen ()
(##list 'IF (##decomp (^ 0))
(##decomp (^ 1))
(##decomp (^ 2)))))
(define ##degen-seq
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1))))
(if (##BEGIN? val2)
(##cons 'BEGIN (##cons val1 (##cdr val2)))
(##list 'BEGIN val1 val2)))))
(define ##degen-quasi-list->vector
(mk-degen ()
(##list 'QUASIQUOTE (##make-vector 1 (##list 'UNQUOTE-SPLICING (##decomp (^ 0)))))))
(define ##degen-quasi-append
(mk-degen ()
(##list 'QUASIQUOTE (##list (##list 'UNQUOTE-SPLICING (##decomp (^ 0)))
(##list 'UNQUOTE-SPLICING (##decomp (^ 1)))))))
(define ##degen-quasi-cons
(mk-degen ()
(##list 'QUASIQUOTE (##list (##list 'UNQUOTE (##decomp (^ 0)))
(##list 'UNQUOTE-SPLICING (##decomp (^ 1)))))))
(define ##degen-cond-if
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1)))
(val3 (##decomp (^ 2))))
(##build-cond
(if (##BEGIN? val2) (##cons val1 (##cdr val2)) (##list val1 val2))
val3))))
(define ##degen-cond-or
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1))))
(##build-cond (##list val1) val2))))
(define ##degen-cond-send
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1)))
(val3 (##decomp (^ 2))))
(##build-cond (##list val1 '=> val2) val3))))
(define (##build-cond clause rest)
(cond ((##COND? rest)
(##cons 'COND (##cons clause (##cdr rest))))
((##BEGIN? rest)
(##cons 'COND (##list clause (##cons 'ELSE (##cdr rest)))))
((##unspecified-obj? rest)
(##list 'COND clause))
(else
(##list 'COND clause (##list 'ELSE rest)))))
(define ##degen-or
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1))))
(if (##OR? val2)
(##cons 'OR (##cons val1 (##cdr val2)))
(##list 'OR val1 val2)))))
(define ##degen-and
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1))))
(if (##AND? val2)
(##cons 'AND (##cons val1 (##cdr val2)))
(##list 'AND val1 val2)))))
(define ##degen-case
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1))))
(##cons 'CASE (##cons val1 val2)))))
(define ##degen-case-clause
(mk-degen ()
(let ((val1 (##decomp (^ 0)))
(val2 (##decomp (^ 1))))
(##cons (if (##BEGIN? val1)
(##cons (^ 2) (##cdr val1))
(##list (^ 2) val1))
val2))))
(define ##degen-case-else
(mk-degen ()
(let ((val (##decomp (^ 0))))
(if (##unspecified-obj? val)
'()
(##list (if (##BEGIN? val)
(##cons 'ELSE (##cdr val))
(##list 'ELSE val)))))))
(define ##degen-let
(mk-degen ()
(let ((n (code-length $code)))
(let loop ((i (##fixnum.- n 2)) (vals '()))
(if (##fixnum.< 0 i)
(loop (##fixnum.- i 1)
(##cons (##decomp (code-ref $code i)) vals))
(let ((body (##decomp (^ 0)))
(bindings (##make-bindings (code-ref $code (##fixnum.- n 1)) vals)))
(if (##BEGIN? body)
(##cons 'LET (##cons bindings (##cdr body)))
(##list 'LET bindings body))))))))
(define (##make-bindings l1 l2)
(if (##pair? l1)
(##cons (##list (##car l1) (##car l2))
(##make-bindings (##cdr l1) (##cdr l2)))
'()))
(define ##degen-letrec
(mk-degen ()
(let ((n (code-length $code)))
(let loop ((i (##fixnum.- n 2)) (vals '()))
(if (##fixnum.< 0 i)
(loop (##fixnum.- i 1)
(##cons (##decomp (code-ref $code i)) vals))
(let ((body (##decomp (^ 0)))
(bindings (##make-bindings (code-ref $code (##fixnum.- n 1)) vals)))
(if (##BEGIN? body)
(##cons 'LETREC (##cons bindings (##cdr body)))
(##list 'LETREC bindings body))))))))
(define ##degen-prc
(mk-degen ()
(let ((body (##decomp (^ 0)))
(params (code-ref $code (##fixnum.- (code-length $code) 1))))
(if (##BEGIN? body)
(##cons 'LAMBDA (##cons params (##cdr body)))
(##list 'LAMBDA params body)))))
(define ##degen-prc-rest
(mk-degen ()
(let ((body (##decomp (^ 0)))
(params (##make-rest-params (^ 2))))
(if (##BEGIN? body)
(##cons 'LAMBDA (##cons params (##cdr body)))
(##list 'LAMBDA params body)))))
(define (##make-rest-params l)
(if (##null? (##cdr l))
(##car l)
(##cons (##car l) (##make-rest-params (##cdr l)))))
(define ##degen-app0
(mk-degen ()
(##list (##decomp (^ 0)))))
(define ##degen-app1
(mk-degen ()
(##list (##decomp (^ 0))
(##decomp (^ 1)))))
(define ##degen-app2
(mk-degen ()
(##list (##decomp (^ 0))
(##decomp (^ 1))
(##decomp (^ 2)))))
(define ##degen-app3
(mk-degen ()
(##list (##decomp (^ 0))
(##decomp (^ 1))
(##decomp (^ 2))
(##decomp (^ 3)))))
(define ##degen-app
(mk-degen ()
(let ((n (code-length $code)))
(let loop ((i (##fixnum.- n 1)) (vals '()))
(if (##not (##fixnum.< i 0))
(loop (##fixnum.- i 1)
(##cons (##decomp (code-ref $code i)) vals))
vals)))))
(define ##degen-delay
(mk-degen ()
(##list 'DELAY (##decomp (^ 0)))))
(define ##degen-future
(mk-degen ()
(##list 'FUTURE (##decomp (^ 0)))))
;------------------------------------------------------------------------------
(define ##decomp-dispatch-table
(##list
(##cons ##cprc-top ##degen-top)
(##cons ##cprc-cst-null (mk-degen () (degen ##degen-cst-x '())))
(##cons ##cprc-cst-true (mk-degen () (degen ##degen-cst-x #t)))
(##cons ##cprc-cst-false (mk-degen () (degen ##degen-cst-x #f)))
(##cons ##cprc-cst--2 (mk-degen () (degen ##degen-cst-x -2)))
(##cons ##cprc-cst--1 (mk-degen () (degen ##degen-cst-x -1)))
(##cons ##cprc-cst-0 (mk-degen () (degen ##degen-cst-x 0)))
(##cons ##cprc-cst-1 (mk-degen () (degen ##degen-cst-x 1)))
(##cons ##cprc-cst-2 (mk-degen () (degen ##degen-cst-x 2)))
(##cons ##cprc-cst ##degen-cst)
(##cons ##cprc-loc-ref-0-1 (mk-degen () (degen ##degen-loc-ref-x-y 0 1)))
(##cons ##cprc-loc-ref-0-2 (mk-degen () (degen ##degen-loc-ref-x-y 0 2)))
(##cons ##cprc-loc-ref-0-3 (mk-degen () (degen ##degen-loc-ref-x-y 0 3)))
(##cons ##cprc-loc-ref-1-1 (mk-degen () (degen ##degen-loc-ref-x-y 1 1)))
(##cons ##cprc-loc-ref-1-2 (mk-degen () (degen ##degen-loc-ref-x-y 1 2)))
(##cons ##cprc-loc-ref-1-3 (mk-degen () (degen ##degen-loc-ref-x-y 1 3)))
(##cons ##cprc-loc-ref-2-1 (mk-degen () (degen ##degen-loc-ref-x-y 2 1)))
(##cons ##cprc-loc-ref-2-2 (mk-degen () (degen ##degen-loc-ref-x-y 2 2)))
(##cons ##cprc-loc-ref-2-3 (mk-degen () (degen ##degen-loc-ref-x-y 2 3)))
(##cons ##cprc-loc-ref ##degen-loc-ref)
(##cons ##cprc-glo-ref ##degen-glo-ref)
(##cons ##cprc-loc-set ##degen-loc-set)
(##cons ##cprc-glo-set ##degen-glo-set)
(##cons ##cprc-glo-def ##degen-glo-def)
(##cons ##cprc-if2 ##degen-if2)
(##cons ##cprc-if3 ##degen-if3)
(##cons ##cprc-seq ##degen-seq)
(##cons ##cprc-quasi-list->vector ##degen-quasi-list->vector)
(##cons ##cprc-quasi-append ##degen-quasi-append)
(##cons ##cprc-quasi-cons ##degen-quasi-cons)
(##cons ##cprc-cond-if ##degen-cond-if)
(##cons ##cprc-cond-or ##degen-cond-or)
(##cons ##cprc-cond-send-red ##degen-cond-send)
(##cons ##cprc-cond-send-sub ##degen-cond-send)
(##cons ##cprc-or ##degen-or)
(##cons ##cprc-and ##degen-and)
(##cons ##cprc-case ##degen-case)
(##cons ##cprc-case-clause ##degen-case-clause)
(##cons ##cprc-case-else ##degen-case-else)
(##cons ##cprc-let ##degen-let)
(##cons ##cprc-letrec ##degen-letrec)
(##cons ##cprc-prc0 ##degen-prc)
(##cons ##cprc-prc1 ##degen-prc)
(##cons ##cprc-prc2 ##degen-prc)
(##cons ##cprc-prc3 ##degen-prc)
(##cons ##cprc-prc ##degen-prc)
(##cons ##cprc-prc-rest ##degen-prc-rest)
(##cons ##cprc-app0-red ##degen-app0)
(##cons ##cprc-app1-red ##degen-app1)
(##cons ##cprc-app2-red ##degen-app2)
(##cons ##cprc-app3-red ##degen-app3)
(##cons ##cprc-app-red ##degen-app)
(##cons ##cprc-app0-sub ##degen-app0)
(##cons ##cprc-app1-sub ##degen-app1)
(##cons ##cprc-app2-sub ##degen-app2)
(##cons ##cprc-app3-sub ##degen-app3)
(##cons ##cprc-app-sub ##degen-app)
(##cons ##cprc-delay ##degen-delay)
(##cons ##cprc-future ##degen-future)
))
;------------------------------------------------------------------------------
(define (##decomp $code)
(let ((cprc (code-cprc $code)))
(let ((x (##assq cprc ##decomp-dispatch-table)))
(if x
(degen (##cdr x))
'?))))
(define (##decompile proc)
(define (decomp1 p)
(if (##proc-subproc? p)
(decomp2 (##proc-subproc-parent p) (##proc-subproc-tag p))
(decomp2 p 0)))
(define (decomp2 parent tag)
(let ((info (##proc-debug-info parent)))
(if info
(let ((v (##vector-ref info 0)))
(let loop ((i (##fixnum.- (##vector-length v) 1)))
(if (##fixnum.< i 0)
proc
(let ((x (##vector-ref v i)))
(if (##fixnum.= tag (##vector-ref x 0))
(source->expression (##vector-ref x 1))
(loop (##fixnum.- i 1)))))))
proc)))
(define (source-code x)
(##vector-ref x 0))
(define (source->expression source)
(define (list->expression l)
(cond ((##pair? l)
(##cons (source->expression (##car l))
(list->expression (##cdr l))))
((##null? l)
'())
(else
(source->expression l))))
(define (vector->expression v)
(let* ((len (##vector-length v))
(x (##make-vector len #f)))
(let loop ((i (##fixnum.- len 1)))
(if (##not (##fixnum.< i 0))
(begin
(##vector-set! x i (source->expression (##vector-ref v i)))
(loop (##fixnum.- i 1)))))
x))
(let ((code (source-code source)))
(cond ((##pair? code) (list->expression code))
((##vector? code) (vector->expression code))
(else code))))
(cond ((##int-proc? proc)
(##decomp (##int-proc-code proc)))
((##proc-closure? proc)
(decomp1 (##proc-closure-body proc)))
(else
(decomp1 proc))))
;==============================================================================
; Debugger
;------------------------------------------------------------------------------
; Access to interpreter continuation frames
(define (##int-frame-non-subproblem? f)
(let ((parent (##proc-subproc-parent (##frame-ret f))))
(##assq parent ##decomp-dispatch-table)))
(define (##int-frame-subproblem? f)
(let ((parent (##proc-subproc-parent (##frame-ret f))))
(or (##eq? parent ##subproblem-apply0)
(##eq? parent ##subproblem-apply1)
(##eq? parent ##subproblem-apply2)
(##eq? parent ##subproblem-apply3)
(##eq? parent ##subproblem-apply))))
(define (##int-frame-subproblem-code f)
(let ((parent (##proc-subproc-parent (##frame-ret f))))
(if (##eq? parent ##subproblem-apply0)
(##frame-stk-ref f 2)
(##frame-stk-ref f 1))))
(define (##int-frame-subproblem-rte f)
(let ((parent (##proc-subproc-parent (##frame-ret f))))
(if (or (##eq? parent ##subproblem-apply2)
(##eq? parent ##subproblem-apply3))
(##frame-stk-ref f 2)
(##frame-stk-ref f 3))))
;------------------------------------------------------------------------------
; Utilities
(define (##continuation->subproblems cont)
(let loop ((f (##continuation->frame cont)) (l '()))
(if f
(if (##int-frame-non-subproblem? f)
(loop (##frame-next f) l)
(loop (##frame-next f) (##cons f l)))
(##reverse l))))
(define (##eval-within expr f dyn-bindings)
(let ((dyn-env (##cons dyn-bindings (##frame-dyn-env f))))
(if (##int-frame-subproblem? f)
(##eval expr
(##extract-frames (##int-frame-subproblem-code f))
(##int-frame-subproblem-rte f)
dyn-env)
(##eval expr #f #f dyn-env))))
(define (##procedure-name p)
(or (##object->global-var-name p) p))
;------------------------------------------------------------------------------
; Read eval print loop
(define (##repl (in ##stdin) (out ##stdout) (prompt2 ": ") (prompt1 ""))
(##call-with-current-continuation
(lambda (cont) (##read-eval-print in out prompt2 prompt1 cont))))
(define ##repl-write #f)
(set! ##repl-write #f)
(define ##repl-read #f)
(set! ##repl-read #f)
(define (##read-eval-print in out prompt2 prompt1 cont)
(define (repl-start subprobs repl-info dyn-bindings)
(define (repl-read)
(let ((proc ##repl-read))
(if (##procedure? proc)
(proc in)
(##read in))))
(define (repl-write val)
(let ((proc ##repl-write))
(if (##procedure? proc)
(proc val out)
(begin
(##write val out (if-touches #t #f))
(##newline out)))))
(define (repl-n n)
(let loop ((i 0) (s subprobs))
(if (and (##fixnum.< n i) (##pair? (##cdr s)))
(loop (##fixnum.- i 1) (##cdr s))
(let ((f (##car s)))
(##display-subproblem i f out)
(repl i s f)))))
(define (cmd-d)
(let ((l (##cdr (##vector-ref repl-info 3))))
(if (##pair? l)
((##car l) #f)
(begin
(##newline out)
(##write-string "*** ^D again to exit" out)
(##newline out)
(if (##eof-object? (##peek-char in))
(##quit))))))
(define (cmd-t)
(let loop ((l (##vector-ref repl-info 3)))
(if (##pair? (##cdr l))
(loop (##cdr l))
((##car l) #f))))
(define (repl pos subprobs* f)
(##call-with-current-continuation
(lambda (abort)
(##set-car! (##vector-ref repl-info 3) abort)))
(let loop ()
(##newline out)
(##display prompt1 out #f)
(if (##fixnum.< pos 0) (##display pos out #f))
(##display prompt2 out #f)
(let ((expr (repl-read)))
(if (##eof-object? expr)
(begin (cmd-d) (loop))
(if (and (##pair? expr)
(##pair? (##cdr expr))
(##null? (##cddr expr))
(##eq? (##car expr) 'UNQUOTE))
(let ((cmd (##cadr expr)))
(if (##eof-object? cmd)
(begin (cmd-d) (loop))
(case cmd
((?) (##cmd-? out) (loop))
((-) (repl-n (##fixnum.- pos 1)))
((+) (repl-n (##fixnum.+ pos 1)))
((b) (##cmd-b pos subprobs* out) (loop))
((i) (##cmd-i f out) (loop))
((y) (##cmd-y f out) (loop))
((l) (##cmd-l f out) (loop))
((t) (cmd-t))
((d) (cmd-d) (loop))
((r) (##display "Return value: " out #f)
(let ((expr (repl-read)))
(if (##eof-object? expr)
##undef-object
(##eval-within expr f dyn-bindings))))
((q) (##quit))
(else
(if (and (##fixnum? cmd) (##fixnum.< cmd 1))
(repl-n cmd)
(begin
(##write-string "Unknown command ," out)
(##write cmd out #f)
(##newline out)
(loop)))))))
(let ((val (##eval-within expr f dyn-bindings)))
(repl-write val)
(loop)))))))
(repl 0 subprobs (##car subprobs)))
(let ((repl-info (##make-vector 4 #f)))
(let ((prev-info (##dynamic-ref '##REPL-INFO #f))
(dyn-bindings (##list (##cons '##REPL-INFO repl-info))))
(##vector-set! repl-info 0 in)
(##vector-set! repl-info 1 out)
(##vector-set! repl-info 2
(if prev-info
(##fixnum.+ (##vector-ref prev-info 2) 1)
0))
(##vector-set! repl-info 3
(##cons (lambda (x) (##quit))
(if prev-info
(##vector-ref prev-info 3)
'())))
(##dynamic-bind
dyn-bindings
(lambda ()
(repl-start (##continuation->subproblems cont)
repl-info
dyn-bindings))))))
(define (##repl-out)
(let ((repl-info (##dynamic-ref '##REPL-INFO #f)))
(if repl-info
(##vector-ref repl-info 1)
##stdout)))
(define (##debug-repl cont)
(let ((repl-info (##dynamic-ref '##REPL-INFO #f)))
(if repl-info
(##read-eval-print (##vector-ref repl-info 0)
(##vector-ref repl-info 1)
": "
(##fixnum.+ (##vector-ref repl-info 2) 1)
cont)
(##read-eval-print ##stdin ##stdout ": " 0 cont))))
(define (##pop-repl)
(let ((repl-info (##dynamic-ref '##REPL-INFO #f)))
(if repl-info
((##car (##vector-ref repl-info 3)) #f)
(##quit))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##cmd-? out)
(##write-string ",? : Summary of commands" out) (##newline out)
(##write-string ",+ and ,- : Move to next or previous frame of continuation" out) (##newline out)
(##write-string ",<n> : Move to particular frame (<n> <= 0)" out) (##newline out)
(##write-string ",b : Display frames of continuation (i.e. backtrace)" out) (##newline out)
(##write-string ",i : Display procedure attached to current frame" out) (##newline out)
(##write-string ",y : Display subproblem of current frame" out) (##newline out)
(##write-string ",l : Display list of local variables accessible in current frame" out) (##newline out)
(##write-string ",t : Transfer to top-level REP loop" out) (##newline out)
(##write-string ",d : Transfer to previous REP loop" out) (##newline out)
(##write-string ",r : Return from REP loop" out) (##newline out)
(##write-string ",q : Quit" out) (##newline out))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##cmd-b pos subprobs* out)
(define max-head 10)
(define max-tail 6)
(let loop ((i 0) (j (##fixnum.- (##length subprobs*) 1)) (l subprobs*))
(if (##pair? l)
(begin
(cond ((or (##fixnum.< i max-head) (##fixnum.< j max-tail)
(and (##fixnum.= i max-head) (##fixnum.= j max-tail)))
(##display-subproblem (##fixnum.- pos i) (##car l) out))
((##fixnum.= i max-head)
(##write-string "..." out) (##newline out)))
(loop (##fixnum.+ i 1) (##fixnum.- j 1) (##cdr l))))))
(define (##display-subproblem pos f out)
(let ((x (##write pos out #f)))
(##display-spaces (##fixnum.- 4 x) out)
(##write-string " " out)
(if (##int-frame-subproblem? f)
(let ((code (##int-frame-subproblem-code f))
(rte (##int-frame-subproblem-rte f)))
(let ((proc (##extract-proc code rte)))
(let ((x (if proc
(##write (##procedure-name proc) out #f)
(##display "(top level)" out #f))))
(##display-spaces (##fixnum.- 25 x) out)
(##write-string " " out)
(##write-string (##object->string (##decomp code) 48 #f) out)
(##newline out))))
(let ((parent (##proc-subproc-parent (##frame-ret f))))
(let ((x (##write (##procedure-name parent) out #f)))
(let ((y (##decompile (##frame-ret f))))
(if (##not (##eq? y (##frame-ret f)))
(begin
(##display-spaces (##fixnum.- 25 x) out)
(##write-string " " out)
(##write-string (##object->string y 48 #f) out)))
(##newline out)))))))
(define (##display-spaces n out)
(if (##fixnum.< 0 n)
(let ((m (if (##fixnum.< 40 n) 40 n)))
(##write-substring " " 0 m out)
(##display-spaces (##fixnum.- n m) out))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##cmd-l f out)
(define (display-locals frames rte)
(let loop1 ((l frames) (r rte))
(if (##pair? l)
(let loop2 ((frame (##car l)) (values (##cdr (##vector->list r))))
(if (##pair? frame)
(let ((var (##car frame)))
(if (##not (or (##eq? var (self-var))
(##eq? var (selector-var))
(##eq? var (do-loop-var))))
(let ((x (##write var out #f)))
(##write-string " = " out)
(##write-string (##object->string
(##car values)
(##fixnum.- (##fixnum.- (##port-width out) 3) x)
(if-touches #t #f))
out)
(##newline out)))
(loop2 (##cdr frame) (##cdr values)))
(loop1 (##cdr l) (rte-up r)))))))
(if (##int-frame-subproblem? f)
(display-locals (##extract-frames (##int-frame-subproblem-code f))
(##int-frame-subproblem-rte f))
(begin
(##write-string "Sorry, can't display compiled code environment" out)
(##newline out))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##cmd-y f out)
(if (##int-frame-subproblem? f)
(##pretty-print (##decomp (##int-frame-subproblem-code f)) out (##port-width out))
(let ((x (##decompile (##frame-ret f))))
(if (##eq? x (##frame-ret f))
(begin
(##write-string "Sorry, this code was compiled without the DEBUG option" out)
(##newline out))
(##pretty-print x out (##port-width out))))))
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(define (##cmd-i f out)
(if (##int-frame-subproblem? f)
(let ((code (##int-frame-subproblem-code f))
(rte (##int-frame-subproblem-rte f)))
(let ((proc (##extract-proc code rte)))
(if proc
(begin
(##write proc out #f)
(##write-string " =" out)
(##newline out)
(##pretty-print (##decompile proc) out (##port-width out)))
(begin
(##write-string "(top level)" out)
(##newline out)))))
(let ((proc (##proc-subproc-parent (##frame-ret f))))
(##write proc out #f)
(let ((x (##decompile proc)))
(if (##eq? x proc)
(##newline out)
(begin
(##write-string " =" out)
(##newline out)
(##pretty-print x out (##port-width out))))))))
;==============================================================================