123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764 |
- ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
- ;;;
- ;;; Port Author: Andrew Whatson
- ;;;
- ;;; Original Authors: Richard Kelsey, Mike Sperber
- ;;;
- ;;; scheme48-1.9.2/ps-compiler/node/node-util.scm
- ;;;
- ;;; This file contains miscellaneous utilities for accessing and modifying the
- ;;; node tree.
- ;;;
- ;;; Get the root of the tree containing node.
- (define-module (ps-compiler node node-util)
- #:use-module (prescheme scheme48)
- #:use-module (ps-compiler node arch)
- #:use-module (ps-compiler node let-nodes)
- #:use-module (ps-compiler node node)
- #:use-module (ps-compiler node primop)
- #:use-module (ps-compiler node variable)
- #:use-module (ps-compiler param)
- #:use-module (ps-compiler util util)
- #:export (node-base containing-procedure
- trivial? nontrivial?
- nontrivial-ancestor
- calls-this-primop?
- bound-to-variable
- walk-refs-safely
- small-node?
- side-effects?
- called-node? called-node
- called-lambda
- get-lambda-value
- ;;set-reference?
- attach-call-args remove-call-args replace-call-args
- remove-null-arguments
- shorten-call-args insert-call-arg remove-call-arg
- append-call-arg
- remove-body
- attach-two-call-args
- attach-three-call-args
- attach-four-call-args
- attach-five-call-args
- remove-lambda-variable remove-variable remove-unused-variables
- substitute substitute-vars-in-node-tree
- replace-call-with-value
- copy-node-tree
- mark-ancestors marked-ancestor? unmarked-ancestor?
- node-ancestor? marked-ancestor least-common-ancestor
- proc-ancestor
- hoistable-node?
- find-scoping
- no-free-references?
- find-calls
- node-type
- the-undefined-value
- undefined-value?
- undefined-value-node?
- make-undefined-literal))
- (define (node-base node)
- (do ((p node (node-parent p)))
- ((not (node? (node-parent p)))
- p)))
- ;; Find the procedure node that contains NODE. Go up one parent at a time
- ;; until a lambda node is found, then go up two at a time, skipping the
- ;; intervening call nodes.
- (define (containing-procedure node)
- (do ((node (node-parent node) (node-parent node)))
- ((lambda-node? node)
- (do ((node node (node-parent (node-parent node))))
- ((proc-lambda? node) node)))))
- ;; Trivial calls are those whose parents are call nodes.
- (define (trivial? call)
- (call-node? (node-parent call)))
- (define (nontrivial? call)
- (lambda-node? (node-parent call)))
- (define (nontrivial-ancestor call)
- (let loop ((call call))
- (if (or (not (node? (node-parent call)))
- (nontrivial? call))
- call
- (loop (node-parent call)))))
- (define (calls-this-primop? call id)
- (eq? id (primop-id (call-primop call))))
- ;; Return the variable to which a value is bound by LET or LETREC.
- (define (bound-to-variable node)
- (let ((parent (node-parent node)))
- (case (primop-id (call-primop parent))
- ((let)
- (if (n= 0 (node-index node))
- (list-ref (lambda-variables (call-arg parent 0))
- (- (node-index node) 1))
- #f))
- ((letrec2)
- (if (< 1 (node-index node))
- (list-ref (lambda-variables
- (variable-binder
- (reference-variable (call-arg parent 1))))
- (- (node-index node) 1))
- #f))
- (else #f))))
- ;; Return a list of all the reference to lambda-node L's value that call it.
- ;; If not all can be identified then #F is returned.
- (define (find-calls l)
- (let ((refs (cond ((bound-to-variable l)
- => variable-refs)
- ((called-node? l)
- (list l))
- (else
- #f))))
- (cond ((and refs (every? called-node? refs))
- refs)
- ((calls-known? l)
- (bug "cannot find calls for known lambda ~S" l))
- (else #f))))
- ;; Walk (or map) a tree-modifying procedure down a variable's references.
- (define (walk-refs-safely proc var)
- (for-each proc (copy-list (variable-refs var))))
- ;; Return #t if the total primop-cost of NODE is less than SIZE.
- (define (small-node? node size)
- (let label ((call (lambda-body node)))
- (set! size (- size (primop-cost call)))
- (if (>= size 0)
- (walk-vector (lambda (n)
- (cond ((lambda-node? n)
- (label (lambda-body n)))
- ((call-node? n)
- (label n))))
- (call-args call))))
- (>= size 0))
- ;; True if executing NODE involves side-effects.
- (define (side-effects? node . permissible)
- (let ((permissible (cons #f permissible)))
- (let label ((node node))
- (cond ((not (call-node? node))
- #f)
- ((and (= 0 (call-exits node))
- (memq (primop-side-effects (call-primop node))
- permissible))
- (let loop ((i (- (call-arg-count node) 1)))
- (cond ((< i 0) #f)
- ((label (call-arg node i)) #t)
- (else (loop (- i 1))))))
- (else
- #t)))))
- ;; A conservative check - is there only one SET-CONTENTS call for the owner and
- ;; are all calls between CALL and the LETREC call that binds the owner calls to
- ;; SET-CONTENTS?
- ;;(define (single-letrec-set? call)
- ;; (let ((owner (call-arg call set/owner)))
- ;; (and (reference-node? owner)
- ;; (every? (lambda (ref)
- ;; (or (eq? (node-parent ref) call)
- ;; (not (set-reference? ref))))
- ;; (variable-refs (reference-variable owner))))))
- ;;(define (set-reference? node)
- ;; (and (eq? 'set-contents
- ;; (primop-id (call-primop (node-parent node))))
- ;; (= (node-index node) set/owner)))
- ;;-------------------------------------------------------------------------------
- (define the-undefined-value (list '*undefined-value*))
- (define (undefined-value? x)
- (eq? x the-undefined-value))
- (define (undefined-value-node? x)
- (and (literal-node? x)
- (undefined-value? (literal-value x))))
- (define (make-undefined-literal)
- (make-literal-node the-undefined-value #f))
- ;;-------------------------------------------------------------------------------
- ;; Finding the lambda node called by CALL, JUMP, or RETURN
- (define (called-node? node)
- (and (node? (node-parent node))
- (eq? node (called-node (node-parent node)))))
- (define (called-node call)
- (cond ((and (primop-procedure? (call-primop call))
- (primop-call-index (call-primop call)))
- => (lambda (i)
- (call-arg call i)))
- (else '#f)))
- (define (called-lambda call)
- (get-lambda-value (call-arg call (primop-call-index (call-primop call)))))
- (define (get-lambda-value value)
- (cond ((lambda-node? value)
- value)
- ((reference-node? value)
- (get-variable-lambda (reference-variable value)))
- (else
- (error "peculiar procedure in ~S" value))))
- (define (get-variable-lambda variable)
- (if (global-variable? variable)
- (or (variable-known-lambda variable)
- (error "peculiar procedure variable ~S" variable))
- (let* ((binder (variable-binder variable))
- (index (node-index binder))
- (call (node-parent binder))
- (lose (lambda ()
- (error "peculiar procedure variable ~S" variable))))
- (case (primop-id (call-primop call))
- ((let)
- (if (= 0 index)
- (get-lambda-value (call-arg call (+ 1 (variable-index variable))))
- (lose)))
- ((letrec1)
- (if (= 0 index)
- (get-letrec-variable-lambda variable)
- (lose)))
- ((call)
- (if (and (= 1 index)
- (= 0 (variable-index variable))) ;; var is a continuation var
- (get-lambda-value (call-arg call 0))
- (lose)))
- (else
- (lose))))))
- ;; Some of the checking can be removed once I know the LETREC code works.
- (define (get-letrec-variable-lambda variable)
- (let* ((binder (variable-binder variable))
- (call (lambda-body binder)))
- (if (and (eq? 'letrec2 (primop-id (call-primop call)))
- (reference-node? (call-arg call 1))
- (eq? (car (lambda-variables binder))
- (reference-variable (call-arg call 1))))
- (call-arg call (+ 1 (variable-index variable)))
- (error "LETREC is incorrectly organized ~S" (node-parent binder)))))
- ;;(define (get-cell-variable-lambda variable)
- ;; (let ((ref (first set-reference? (variable-refs variable))))
- ;; (if (and ref
- ;; (eq? 'letrec
- ;; (literal-value (call-arg (node-parent ref) set/type))))
- ;; (get-lambda-value (call-arg (node-parent ref) set/value))
- ;; (error "peculiar lambda cell ~S" variable))))
- ;;-------------------------------------------------------------------------------
- ;; Attaching and detaching arguments to calls
- ;; Make ARGS the arguments of call node PARENT. ARGS may contain #f.
- (define (attach-call-args parent args)
- (let ((len (call-arg-count parent)))
- (let loop ((args args) (i 0))
- (cond ((null? args)
- (if (< i (- len 1))
- (bug '"too few arguments added to node ~S" parent))
- (values))
- ((>= i len)
- (bug '"too many arguments added to node ~S" parent))
- (else
- (if (car args)
- (attach parent i (car args)))
- (loop (cdr args) (+ 1 i)))))))
- ;; Remove all of the arguments of NODE.
- (define (remove-call-args node)
- (let ((len (call-arg-count node)))
- (do ((i 1 (+ i 1)))
- ((>= i len))
- (if (not (empty? (call-arg node i)))
- (erase (detach (call-arg node i)))))
- (values)))
- ;; Replace the arguments of call node NODE with NEW-ARGS.
- (define (replace-call-args node new-args)
- (let ((len (length new-args)))
- (remove-call-args node)
- (if (n= len (call-arg-count node))
- (let ((new (make-vector len empty))
- (old (call-args node)))
- (set-call-args! node new)))
- (attach-call-args node new-args)))
- ;; Remove all arguments to CALL that are EMPTY?. COUNT is the number of
- ;; non-EMPTY? arguments.
- (define (remove-null-arguments call count)
- (let ((old (call-args call))
- (new (make-vector count empty)))
- (let loop ((i 0) (j 0))
- (cond ((>= j count)
- (values))
- ((not (empty? (vector-ref old i)))
- (set-node-index! (vector-ref old i) j)
- (vector-set! new j (vector-ref old i))
- (loop (+ i 1) (+ j 1)))
- (else
- (loop (+ i 1) j))))
- (set-call-args! call new)
- (values)))
- ;; Remove all but the first COUNT arguments from CALL.
- (define (shorten-call-args call count)
- (let ((old (call-args call))
- (new (make-vector count empty)))
- (vector-replace new old count)
- (do ((i (+ count 1) (+ i 1)))
- ((>= i (vector-length old)))
- (erase (vector-ref old i)))
- (set-call-args! call new)
- (values)))
- ;; Insert ARG as the INDEXth argument to CALL.
- (define (insert-call-arg call index arg)
- (let* ((old (call-args call))
- (len (vector-length old))
- (new (make-vector (+ 1 len) empty)))
- (vector-replace new old index)
- (do ((i index (+ i 1)))
- ((>= i len))
- (vector-set! new (+ i 1) (vector-ref old i))
- (set-node-index! (vector-ref old i) (+ i 1)))
- (set-call-args! call new)
- (attach call index arg)
- (values)))
- ;; Remove the INDEXth argument to CALL.
- (define (remove-call-arg call index)
- (let* ((old (call-args call))
- (len (- (vector-length old) 1))
- (new (make-vector len)))
- (vector-replace new old index)
- (if (node? (vector-ref old index))
- (erase (detach (vector-ref old index))))
- (do ((i index (+ i 1)))
- ((>= i len))
- (vector-set! new i (vector-ref old (+ i 1)))
- (set-node-index! (vector-ref new i) i))
- (set-call-args! call new)
- (if (< index (call-exits call))
- (set-call-exits! call (- (call-exits call) 1)))
- (values)))
- ;; Add ARG to the end of CALL's arguments.
- (define (append-call-arg call arg)
- (insert-call-arg call (call-arg-count call) arg))
- ;; Replace CALL with the body of its continuation.
- (define (remove-body call)
- (if (n= 1 (call-exits call))
- (bug "removing a call with ~D exits" (call-exits call))
- (replace-body call (detach-body (lambda-body (call-arg call 0))))))
- ;; Avoiding N-Ary Procedures
- ;; These are used in the expansion of the LET-NODES macro.
- (define (attach-two-call-args node a0 a1)
- (attach node 0 a0)
- (attach node 1 a1))
- (define (attach-three-call-args node a0 a1 a2)
- (attach node 0 a0)
- (attach node 1 a1)
- (attach node 2 a2))
- (define (attach-four-call-args node a0 a1 a2 a3)
- (attach node 0 a0)
- (attach node 1 a1)
- (attach node 2 a2)
- (attach node 3 a3))
- (define (attach-five-call-args node a0 a1 a2 a3 a4)
- (attach node 0 a0)
- (attach node 1 a1)
- (attach node 2 a2)
- (attach node 3 a3)
- (attach node 4 a4))
- ;;-------------------------------------------------------------------------------
- ;; Changing lambda-nodes' variable lists
- (define (remove-lambda-variable l-node index)
- (remove-variable l-node (list-ref (lambda-variables l-node) index)))
- (define (remove-variable l-node var)
- (if (used? var)
- (bug '"cannot remove referenced variable ~s" var))
- (erase-variable var)
- (let ((vars (lambda-variables l-node)))
- (if (eq? (car vars) var)
- (set-lambda-variables! l-node (cdr vars))
- (do ((vars vars (cdr vars)))
- ((eq? (cadr vars) var)
- (set-cdr! vars (cddr vars)))))))
- ;; Remove all of L-NODES' unused variables.
- (define (remove-unused-variables l-node)
- (set-lambda-variables! l-node
- (filter! (lambda (v)
- (cond ((used? v)
- #t)
- (else
- (erase-variable v)
- #f)))
- (lambda-variables l-node))))
- ;;------------------------------------------------------------------------------
- ;; Substituting Values For Variables
- ;; Substitute VAL for VAR. If DETACH? is true then VAL should be detached
- ;; and so can be used instead of a copy for the first substitution.
- ;;
- ;; If VAL is a reference to a variable named V, it was probably introduced by
- ;; the CPS conversion code. In that case, the variable is renamed with the
- ;; name of VAR. This helps considerably when debugging the compiler.
- (define (substitute var val detach?)
- (if (and (reference-node? val)
- (eq? 'v (variable-name (reference-variable val)))
- (not (global-variable? (reference-variable val))))
- (set-variable-name! (reference-variable val)
- (variable-name var)))
- (let ((refs (variable-refs var)))
- (set-variable-refs! var '())
- (cond ((not (null? refs))
- (for-each (lambda (ref)
- (replace ref (copy-node-tree val)))
- (if detach? (cdr refs) refs))
- (if detach? (replace (car refs) (detach val))))
- (detach?
- (erase (detach val))))))
- ;; Walk the tree NODE replacing references to variables in OLD-VARS with
- ;; the corresponding variables in NEW-VARS. Uses VARIABLE-FLAG to mark
- ;; the variables being replaced.
- (define (substitute-vars-in-node-tree node old-vars new-vars)
- (for-each (lambda (old new)
- (set-variable-flag! old new))
- old-vars
- new-vars)
- (let tree-walk ((node node))
- (cond ((lambda-node? node)
- (walk-vector tree-walk (call-args (lambda-body node))))
- ((call-node? node)
- (walk-vector tree-walk (call-args node)))
- ((and (reference-node? node)
- (variable-flag (reference-variable node)))
- => (lambda (new)
- (replace node (make-reference-node new))))))
- (for-each (lambda (old)
- (set-variable-flag! old #f))
- old-vars))
- ;; Replaces the call node CALL with VALUE.
- ;; (<proc> <exit> . <args>) => (<exit> <value>)
- (define (replace-call-with-value call value)
- (cond ((n= 1 (call-exits call))
- (bug '"can only substitute for call with one exit ~s" call))
- (else
- (let ((cont (detach (call-arg call 0))))
- (set-call-exits! call 0)
- (replace-call-args call (if value (list cont value) (list cont)))
- (set-call-primop! call (get-primop (enum primop-enum let)))))))
- ;;------------------------------------------------------------------------------
- ;; Copying Node Trees
- ;; Copy the node-tree NODE. This dispatches on the type of NODE.
- ;; Variables which have been copied have the copy in the node-flag field.
- (define (copy-node-tree node)
- (let ((new (cond ((lambda-node? node)
- (copy-lambda node))
- ((reference-node? node)
- (let ((var (reference-variable node)))
- (cond ((and (variable-binder var)
- (variable-flag var))
- => make-reference-node)
- (else
- (make-reference-node var)))))
- ((call-node? node)
- (copy-call node))
- ((literal-node? node)
- (copy-literal-node node)))))
- new))
- ;; Copy a lambda node and its variables. The variables' copies are put in
- ;; their VARIABLE-FLAG while the lambda's body is being copied.
- (define (copy-lambda node)
- (let* ((vars (map (lambda (var)
- (if var
- (let ((new (copy-variable var)))
- (set-variable-flag! var new)
- new)
- #f))
- (lambda-variables node)))
- (new-node (make-lambda-node (lambda-name node)
- (lambda-type node)
- vars)))
- (attach-body new-node (copy-call (lambda-body node)))
- (set-lambda-protocol! new-node (lambda-protocol node))
- (set-lambda-source! new-node (lambda-source node))
- (for-each (lambda (var)
- (if var (set-variable-flag! var #f)))
- (lambda-variables node))
- new-node))
- (define (copy-call node)
- (let ((new-node (make-call-node (call-primop node)
- (call-arg-count node)
- (call-exits node))))
- (do ((i 0 (+ i 1)))
- ((>= i (call-arg-count node)))
- (attach new-node i (copy-node-tree (call-arg node i))))
- (set-call-source! new-node (call-source node))
- new-node))
- ;;------------------------------------------------------------------------------
- ;; Checking the scoping of identifers
- ;; Mark all ancestors of N with FLAG
- (define (mark-ancestors n flag)
- (do ((n n (node-parent n)))
- ((not (node? n)) (values))
- (set-node-flag! n flag)))
- ;; Does N have an ancestor with a non-#f flag?
- (define (marked-ancestor? n)
- (do ((n n (node-parent n)))
- ((or (not (node? n))
- (node-flag n))
- (node? n))))
- ;; Does N have an ancestor with a #f flag?
- (define (unmarked-ancestor? n)
- (do ((n n (node-parent n)))
- ((or (not (node? n))
- (not (node-flag n)))
- (node? n))))
- ;; Is ANC? an ancestor of NODE?
- (define (node-ancestor? anc? node)
- (set-node-flag! anc? #t)
- (let ((okay? (marked-ancestor? node)))
- (set-node-flag! anc? #f)
- okay?))
- ;; Find the lowest ancestor of N that has a non-#f flag
- (define (marked-ancestor n)
- (do ((n n (node-parent n)))
- ((or (not (node? n))
- (node-flag n))
- (if (node? n) n #f))))
- ;; Mark the ancestors of START with #f, stopping when END is reached
- (define (unmark-ancestors-to start end)
- (do ((node start (node-parent node)))
- ((eq? node end))
- (set-node-flag! node #f)))
- ;; Return the lowest node that is above all NODES
- (define (least-common-ancestor nodes)
- (mark-ancestors (car nodes) #t)
- (let loop ((nodes (cdr nodes)) (top (car nodes)))
- (cond ((null? nodes)
- (mark-ancestors top #f)
- top)
- (else
- (let ((new (marked-ancestor (car nodes))))
- (unmark-ancestors-to top new)
- (loop (cdr nodes) new))))))
- ;; Can TO be moved to FROM without taking variables out of scope.
- ;; This first marks all of the ancestors of FROM, and then unmarks all of the
- ;; ancestors of TO. The net result is to mark every node that is above FROM but
- ;; not above TO. Then if any reference-node below FROM references a variable
- ;; with a marked binder, that node, and thus FROM itself, cannot legally be
- ;; moved to TO.
- ;; This is not currently used anywhere, and it doesn't know about trivial
- ;; calls.
- (define (hoistable-node? from to)
- (let ((from (if (call-node? from)
- (node-parent (nontrivial-ancestor from))
- from)))
- (mark-ancestors (node-parent from) #t)
- (mark-ancestors to #f)
- (let ((okay? (let label ((n from))
- (cond ((lambda-node? n)
- (let* ((vec (call-args (lambda-body n)))
- (c (vector-length vec)))
- (let loop ((i 0))
- (cond ((>= i c) #t)
- ((label (vector-ref vec i))
- (loop (+ i 1)))
- (else #f)))))
- ((reference-node? n)
- (let ((b (variable-binder (reference-variable n))))
- (or (not b) (not (node-flag b)))))
- (else #t)))))
- (mark-ancestors (node-parent from) #f)
- okay?)))
- ;; Mark all of the lambda nodes which bind variables referenced below NODE.
- (define (mark-binders node)
- (let label ((n node))
- (cond ((lambda-node? n)
- (walk-vector label (call-args (lambda-body n))))
- ((reference-node? n)
- (let ((b (variable-binder (reference-variable n))))
- (if b (set-node-flag! b #f))))))
- (values))
- ;;------------------------------------------------------------------------------
- ;; For each lambda-node L this sets (PARENT L) to be the enclosing PROC node
- ;; of L and, if L is a PROC node, sets (KIDS L) to be the lambda nodes it
- ;; encloses.
- (define (find-scoping lambdas parent set-parent! kids set-kids!)
- (receive (procs others)
- (partition-list proc-lambda? lambdas)
- (for-each (lambda (l)
- (set-parent! l #f)
- (set-kids! l '()))
- procs)
- (for-each (lambda (l)
- (set-parent! l #f))
- others)
- (letrec ((set-lambda-parent!
- (lambda (l)
- (cond ((parent l)
- => identity)
- ((proc-ancestor l)
- => (lambda (p)
- (let ((p (if (proc-lambda? p)
- p
- (set-lambda-parent! p))))
- (set-kids! p (cons l (kids p)))
- (set-parent! l p)
- p)))
- (else #f)))))
- (for-each set-lambda-parent! lambdas))
- (values procs others)))
- (define (proc-ancestor node)
- (let ((p (node-parent node)))
- (if (not (node? p))
- #f
- (let ((node (do ((p p (node-parent p)))
- ((lambda-node? p)
- p))))
- (do ((node node (node-parent (node-parent node))))
- ((proc-lambda? node)
- node))))))
- (define (no-free-references? node)
- (if (call-node? node)
- (error "NO-FREE-REFERENCES only works on value nodes: ~S" node))
- (let label ((node node))
- (cond ((reference-node? node)
- (let ((b (variable-binder (reference-variable node))))
- (or (not b)
- (node-flag b))))
- ((lambda-node? node)
- (set-node-flag! node #t)
- (let ((res (label (lambda-body node))))
- (set-node-flag! node #f)
- res))
- ((call-node? node)
- (let ((vec (call-args node)))
- (let loop ((i (- (vector-length vec) 1)))
- (cond ((< i 0) #t)
- ((not (label (vector-ref vec i))) #f)
- (else (loop (- i 1)))))))
- (else #t))))
- (define (node-type node)
- (cond ((literal-node? node)
- (literal-type node))
- ((reference-node? node)
- (variable-type (reference-variable node)))
- ((lambda-node? node)
- (lambda-node-type node))
- ((and (call-node? node)
- (primop-trivial? (call-primop node)))
- (trivial-call-return-type node))
- (else
- (error "node ~S does not represent a value" node))))
- ;;----------------------------------------------------------------
- ;; Debugging utilities
- (define (show-simplified node)
- (let loop ((n node) (r '()))
- (if (node? n)
- (loop (node-parent n) (cons (node-simplified? n) r))
- (reverse r))))
- (define (show-flag node)
- (let loop ((n node) (r '()))
- (if (node? n)
- (loop (node-parent n) (cons (node-flag n) r))
- (reverse r))))
- (define (reset-simplified node)
- (let loop ((n node))
- (cond ((node? n)
- (set-node-simplified?! n #f)
- (loop (node-parent n))))))
|