;;; Ported from Scheme 48 1.9. See file COPYING for notices and license. ;;; ;;; Port Author: Andrew Whatson ;;; ;;; Original Authors: Richard Kelsey, Jonathan Rees, Mike Sperber ;;; ;;; scheme48-1.9.2/scheme/bcomp/node.scm (define-module (prescheme bcomp node) #:use-module (srfi srfi-9) #:use-module (prescheme scheme48) #:use-module (prescheme bcomp mtype) #:use-module (prescheme record-discloser) #:export (make-node node? node-operator node-operator-id node-form node-ref node-set! node-predicate make-similar-node force-node schemify name->qualified get-operator make-operator-table operator-name operator-nargs operator-table-ref operator-define! operator-lookup operator-type operator-uid operator? operators-table ;;config.scm comp-package.scm lambda-node? flat-lambda-node? name-node? call-node? literal-node? quote-node? define-node? loophole-node? operator/flat-lambda operator/lambda operator/set! operator/call operator/begin operator/name operator/letrec operator/letrec* operator/pure-letrec operator/literal operator/quote operator/unassigned operator/unspecific operator/define operator/define-syntax operator/primitive-procedure operator/structure-ref)) ;; -------------------- ;; Operators (= special operators and primitives) (define-record-type :operator (make-operator type nargs uid name) operator? (type operator-type set-operator-type!) (nargs operator-nargs) (uid operator-uid) (name operator-name)) (define-record-discloser :operator (lambda (s) (list 'operator (operator-name s) (if (symbol? (operator-type s)) (operator-type s) (type->sexp (operator-type s) #t))))) (define usual-operator-type (procedure-type any-arguments-type value-type #f)) (define (get-operator name . type-option) (let ((type (if (null? type-option) #f (car type-option))) (probe (table-ref operators-table name))) (if (operator? probe) (let ((previous-type (operator-type probe))) (cond ((not type)) ((not previous-type) (set-operator-type! probe type)) ((symbol? type) ;; 'leaf or 'internal (if (not (eq? type previous-type)) (warning 'get-operator "operator type inconsistency" name type previous-type))) ((subtype? type previous-type) ;;Improvement (set-operator-type! probe type)) ((not (subtype? previous-type type)) (warning 'get-operator "operator type inconsistency" name (type->sexp previous-type 'foo) (type->sexp type 'foo)))) probe) (let* ((uid *operator-uid*) (op (make-operator type (if (and type (not (symbol? type)) (fixed-arity-procedure-type? type)) (procedure-type-arity type) #f) uid name))) (if (>= uid number-of-operators) (warning 'get-operator "too many operators" (operator-name op) (operator-type op))) (set! *operator-uid* (+ *operator-uid* 1)) (table-set! operators-table (operator-name op) op) (vector-set! the-operators uid op) op)))) (define *operator-uid* 0) (define operators-table (make-table)) (define number-of-operators 400) ;;Fixed-size limits bad, but speed good (define the-operators (make-vector number-of-operators #f)) ;; -------------------- ;; Operator tables (for fast dispatch) (define (make-operator-table default) (make-vector number-of-operators default)) (define operator-table-ref vector-ref) (define (operator-lookup table op) (operator-table-ref table (operator-uid op))) (define (operator-define! table name type proc) (vector-set! table (operator-uid (get-operator name type)) proc)) ;; -------------------- ;; Nodes ;; A node is an annotated expression (or definition or other form). ;; The FORM component of a node is an S-expression of the same form as ;; the S-expression representation of the expression. E.g. for ;; literals, the form is the literal value; for variables the form is ;; the variable name; for IF expressions the form is a 4-element list ;; ( test con alt). Nodes also have a tag identifying what kind ;; of node it is (literal, variable, if, etc.) and a property list. (define-record-type :node (really-make-node uid form plist) node? (uid node-operator-id) (form node-form) (plist node-plist set-node-plist!)) (define-record-discloser :node (lambda (n) (list (operator-name (node-operator n)) (node-form n)))) (define (make-node operator form) (really-make-node (operator-uid operator) form '())) (define (node-ref node key) (let ((probe (assq key (node-plist node)))) (if probe (cdr probe) #f))) ;; removes property if value is #f (define (node-set! node key value) ;;gross (if value (let ((probe (assq key (node-plist node)))) (if probe (set-cdr! probe value) (set-node-plist! node (cons (cons key value) (node-plist node))))) (let loop ((l (node-plist node)) (prev #f)) (cond ((null? l) 'lose) ((eq? key (caar l)) (if prev (set-cdr! prev (cdr l)) (set-node-plist! node (cdr l)))) (else (loop (cdr l) l)))))) (define (node-operator node) (vector-ref the-operators (node-operator-id node))) (define (node-predicate name . type-option) (let ((id (operator-uid (apply get-operator name type-option)))) (lambda (node) (= (node-operator-id node) id)))) (define (make-similar-node node form) (if (equal? form (node-form node)) node (make-node (node-operator node) form))) ;; Top-level nodes are often delayed. (define (force-node node) (if (node? node) node (force node))) ;; Node predicates and operators. (define lambda-node? (node-predicate 'lambda syntax-type)) (define flat-lambda-node? (node-predicate 'flat-lambda syntax-type)) (define call-node? (node-predicate 'call)) (define name-node? (node-predicate 'name 'leaf)) (define literal-node? (node-predicate 'literal 'leaf)) (define quote-node? (node-predicate 'quote syntax-type)) (define define-node? (node-predicate 'define)) (define loophole-node? (node-predicate 'loophole)) (define operator/flat-lambda (get-operator 'flat-lambda)) (define operator/lambda (get-operator 'lambda syntax-type)) (define operator/set! (get-operator 'set! syntax-type)) (define operator/call (get-operator 'call 'internal)) (define operator/begin (get-operator 'begin syntax-type)) (define operator/name (get-operator 'name 'leaf)) (define operator/letrec (get-operator 'letrec)) (define operator/letrec* (get-operator 'letrec*)) (define operator/pure-letrec (get-operator 'pure-letrec)) (define operator/literal (get-operator 'literal)) (define operator/quote (get-operator 'quote syntax-type)) (define operator/unassigned (get-operator 'unassigned)) (define operator/unspecific (get-operator 'unspecific (proc () unspecific-type))) (define operator/define (get-operator 'define syntax-type)) (define operator/define-syntax (get-operator 'define-syntax syntax-type)) (define operator/primitive-procedure (get-operator 'primitive-procedure syntax-type)) (define operator/structure-ref (get-operator 'structure-ref syntax-type))