1 ;;;============================================================================
3 ;;; File: "_ptree2.scm", Time-stamp: <2009-07-04 17:17:17 feeley>
5 ;;; Copyright (c) 1994-2009 by Marc Feeley, All Rights Reserved.
9 (include-adt "_envadt.scm")
10 (include-adt "_gvmadt.scm")
11 (include-adt "_ptreeadt.scm")
12 (include-adt "_sourceadt.scm")
14 '(begin;**********brad
15 (##include "../gsc/_utilsadt.scm")
16 (##include "../gsc/_envadt.scm")
17 (##include "../gsc/_ptree1adt.scm")
18 (##include "../gsc/_hostadt.scm")
21 ;;;----------------------------------------------------------------------------
23 ;; Parse tree manipulation module: (part 2)
24 ;; ------------------------------
26 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
28 (define (normalize-program ptrees)
29 (let* ((lst1 (expand-primitive-calls ptrees))
30 (lst2 (assignment-convert lst1))
31 (lst3 (beta-reduce lst2))
32 (lst4 (lambda-lift lst3)))
35 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
37 ;; (delete-ptree ptree) removes parse tree 'ptree' from program and updates
38 ;; references and assignments to variables.
40 (define (delete-ptree ptree)
43 (let ((var (ref-var ptree)))
44 (var-refs-set! var (ptset-remove (var-refs var) ptree))))
47 (let ((var (set-var ptree)))
48 (var-sets-set! var (ptset-remove (var-sets var) ptree))))
51 (let ((var (def-var ptree)))
52 (var-sets-set! var (ptset-remove (var-sets var) ptree)))))
54 (for-each delete-ptree (node-children ptree)))
56 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
58 ;; (clone-ptree ptree) returns a fresh copy of 'ptree'. All the
59 ;; bound variables (i.e. not free variables) in ptree are also copied.
60 ;; It is assumed that 'ptree' has already been assignment-converted.
62 (define (clone-ptree ptree)
65 (define (cp ptree substs)
67 (define (rename-var var)
68 (let ((x (assq var substs)))
72 (new-cst (node-source ptree) (node-env ptree)
76 (let ((var (rename-var (ref-var ptree))))
77 (new-ref (node-source ptree) (node-env ptree)
81 (let ((var (rename-var (set-var ptree))))
82 (new-set (node-source ptree) (node-env ptree)
84 (cp (set-val ptree) substs))))
86 ((def? ptree) ; guaranteed to be a toplevel definition
87 (new-def (node-source ptree) (node-env ptree)
89 (cp (def-val ptree) substs)))
92 (new-tst (node-source ptree) (node-env ptree)
93 (cp (tst-pre ptree) substs)
94 (cp (tst-con ptree) substs)
95 (cp (tst-alt ptree) substs)))
98 (new-conj (node-source ptree) (node-env ptree)
99 (cp (conj-pre ptree) substs)
100 (cp (conj-alt ptree) substs)))
103 (new-disj (node-source ptree) (node-env ptree)
104 (cp (disj-pre ptree) substs)
105 (cp (disj-alt ptree) substs)))
108 (let* ((parms (prc-parms ptree))
109 (vars (clone-vars parms)))
110 (new-prc (node-source ptree) (node-env ptree)
118 (append (pair-up parms vars) substs)))))
121 (let ((oper (app-oper ptree))
122 (args (app-args ptree)))
123 (if (and (prc? oper) ; applying a lambda-expr is like a 'let'
124 (prc-req-and-opt-parms-only? oper)
125 (= (length (prc-parms oper)) (length args)))
126 (let* ((parms (prc-parms oper))
127 (vars (clone-vars parms))
128 (new-substs (append (pair-up parms vars) substs)))
132 (map (lambda (x) (cp x new-substs)) args)
133 (cp (prc-body oper) new-substs)))
134 (new-call (node-source ptree) (node-env ptree)
135 (cp (app-oper ptree) substs)
136 (map (lambda (x) (cp x substs)) (app-args ptree))))))
139 (new-fut (node-source ptree) (node-env ptree)
140 (cp (fut-val ptree) substs)))
143 (compiler-internal-error "cp, unknown parse tree node type"))))
145 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
147 ;; Expansion of primitive calls
148 ;; ----------------------------
150 ;; (expand-primitive-calls lst) takes a list of parse-trees and returns
151 ;; a list where each parse-tree has been replaced with an equivalent
152 ;; parse-tree where some calls to primitive procedures have been
153 ;; expanded into an equivalent, but probably faster, Scheme expression.
155 (define (expand-primitive-calls lst)
160 (cond ((or (cst? ptree)
162 (def? ptree) ; guaranteed to be a toplevel definition
168 (node-children-set! ptree
170 (node-children ptree)))
174 (let ((proc (global-proc-obj ptree)))
177 (new-cst (node-source ptree) (node-env ptree)
187 (map epc (app-args ptree)))
190 (let ((var (ref-var oper)))
195 (target.prim-info name))
197 (specialize-proc proc args (node-env oper)))
203 (inline-primitive? name env)
204 (or ((proc-obj-inlinable? spec) env)
205 ((proc-obj-expandable? spec) env)))
207 (standard-proc-obj proc
211 (run-time-binding? name
213 (generate-original-call
217 (add-not-inline-primitive? env)
218 (new-ref (node-source oper)
221 (gen-var-refs source env vars))))
222 (generate-run-time-binding-test
224 (let ((vars (gen-temp-vars source args)))
228 (gen-eq-proc source env
235 (generate-original-call vars))))))
237 (if ((proc-obj-inlinable? spec) env)
242 (generate-run-time-binding-test
247 (gen-var-refs source env vars)))))
253 ((proc-obj-expand spec)
258 generate-original-call
263 (gen-var-refs source env vars))))
267 (gen-eq-proc source env
275 (not (eq? proc spec)))
276 (generate-run-time-binding-test
280 (gen-var-refs source env vars))))
294 (proc-obj? (cst-val oper)))
298 (specialize-proc proc args (node-env oper)))
305 (inline-primitive? (proc-obj-name spec) env)
306 ((proc-obj-expandable? spec) env)
307 ((proc-obj-expand spec)
314 (add-not-inline-primitive? env)
317 (gen-var-refs source env vars)))
324 (node-children-set! ptree
331 (compiler-internal-error "epc, unknown parse tree node type"))))
333 (define (gen-prc source env params body)
334 (new-prc source env #f #f params '() #f #f body))
336 (define (gen-disj-multi source env nodes)
337 (if (pair? (cdr nodes))
340 (gen-disj-multi source env (cdr nodes)))
343 (define (gen-uniform-type-checks source env vars type-check tail)
345 (define (loop result lst)
347 (loop (new-conj source env
348 (type-check (car lst))
356 (loop (type-check (car vars)) (cdr vars)))
360 (define (gen-temp-vars source args)
361 (let loop ((args args) (rev-vars '()))
365 (cons (new-temp-variable source 'temp)
368 (define (gen-var-refs source env vars)
374 (define (gen-call-prim-vars source env prim vars)
375 (gen-call-prim source env
377 (gen-var-refs source env vars)))
379 (define (gen-call-prim source env prim args)
380 (new-call source (add-not-safe env)
382 (target.prim-info prim))
385 (define (gen-eq-proc source env arg proc)
386 (gen-call-prim source env
393 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
395 ;; Assignment conversion:
396 ;; ---------------------
398 ;; (assignment-convert lst) takes a list of parse-trees and returns a
399 ;; list where each parse-tree has been replaced with an equivalent
400 ;; parse-tree containing no assignments to non-global variables. In
401 ;; the converted parse-tree, 'box' objects are used to implement mutable
402 ;; variables and calls to the procedures:
408 ;; are added to create and access the boxes.
410 (define (assignment-convert lst)
411 (map (lambda (ptree) (ac ptree '()))
414 (define (ac ptree mut)
420 (let ((var (ref-var ptree)))
423 (let ((x (assq var mut)))
425 (let ((source (node-source ptree)))
426 (var-refs-set! var (ptset-remove (var-refs var) ptree))
427 (gen-call-prim source (node-env ptree)
429 (list (new-ref source (node-env ptree) (cdr x)))))
433 (let ((var (set-var ptree))
434 (source (node-source ptree))
435 (val (ac (set-val ptree) mut)))
438 (var-sets-set! var (ptset-remove (var-sets var) ptree))
439 (new-set source (node-env ptree)
442 (gen-call-prim source (node-env ptree)
444 (list (new-ref source (node-env ptree) (cdr (assq var mut)))
447 ((def? ptree) ; guaranteed to be a toplevel definition
448 (let ((var (def-var ptree))
449 (val (ac (def-val ptree) mut)))
450 (var-sets-set! var (ptset-remove (var-sets var) ptree))
451 (new-def (node-source ptree) (node-env ptree)
456 (new-tst (node-source ptree) (node-env ptree)
457 (ac (tst-pre ptree) mut)
458 (ac (tst-con ptree) mut)
459 (ac (tst-alt ptree) mut)))
462 (new-conj (node-source ptree) (node-env ptree)
463 (ac (conj-pre ptree) mut)
464 (ac (conj-alt ptree) mut)))
467 (new-disj (node-source ptree) (node-env ptree)
468 (ac (disj-pre ptree) mut)
469 (ac (disj-alt ptree) mut)))
475 (let ((oper (app-oper ptree))
476 (args (app-args ptree)))
477 (if (and (prc? oper) ; applying a lambda-expr is like a 'let'
478 (prc-req-and-opt-parms-only? oper)
479 (= (length (prc-parms oper)) (length args)))
481 (new-call (node-source ptree) (node-env ptree)
483 (map (lambda (x) (ac x mut)) args)))))
486 (new-fut (node-source ptree) (node-env ptree)
487 (ac (fut-val ptree) mut)))
490 (compiler-internal-error "ac, unknown parse tree node type"))))
492 (define (ac-proc ptree mut)
493 (let* ((mut-parms (ac-mutables (prc-parms ptree)))
494 (cloned-mut-parms (clone-vars mut-parms)))
496 (for-each (lambda (var) (var-sets-set! var (ptset-empty)))
499 (for-each (lambda (var) (var-boxed?-set! var #t))
502 (new-prc (node-source ptree) (node-env ptree)
513 (gen-call-prim (var-source var) (node-env ptree)
515 (list (new-ref (var-source var)
520 (append (pair-up mut-parms cloned-mut-parms) mut))))))
522 (define (ac-let ptree mut)
523 (let* ((proc (app-oper ptree))
524 (vals (app-args ptree))
525 (vars (prc-parms proc))
526 (vals-fv (varset-union-multi (map bound-free-variables vals)))
527 (mut-parms (ac-mutables vars))
528 (cloned-mut-parms (clone-vars mut-parms))
529 (mut (append (pair-up mut-parms cloned-mut-parms) mut)))
531 (for-each (lambda (var) (var-sets-set! var (ptset-empty)))
534 (for-each (lambda (var) (var-boxed?-set! var #t))
541 (new-body (ac (prc-body proc) mut)))
544 (new-let ptree proc new-vars new-vals new-body)
549 (if (memq var mut-parms)
551 (let ((src (node-source val))
553 (var* (cdr (assq var mut))))
555 (if (varset-member? var vals-fv)
560 (cons (gen-call-prim src env
562 (list (new-cst src env void-object)))
565 (gen-call-prim src env
567 (list (new-ref src env var*)
574 (cons (gen-call-prim src env
583 (cons (ac val mut) new-vals)
586 (define (ac-mutables lst)
589 (define (clone-vars vars)
592 (make-var (var-name var)
597 (var-boxed?-set! cloned-var (var-boxed? var))
601 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
606 ;; (beta-reduce ptrees) takes a list of parse-trees and transforms
607 ;; each parse-tree with the following transformations:
609 ;; - constant propagation
610 ;; - copy propagation
611 ;; - useless variable elimination
613 ;; It is assumed that the parse-trees have already been assignment-converted.
615 (define beta-reduce #f);***************
617 (set! beta-reduce (lambda (ptrees)
619 (define (vars-with-duplicates->varset vars);********brad avoids this because list->set removes duplicates
620 (let loop ((set (varset-empty)) (lst vars))
622 (loop (varset-adjoin set (car lst)) (cdr lst))
625 (define (pass1) ; transform definitions in dependency order
629 (vars-with-duplicates->varset (map def-var (reverse defs))))
637 (free-variables (def-val def))))
639 (ptset->list (var-sets var)))))))
640 (varset->list defined-vars)))
643 (transitive-closure depgraph))))
652 (list (br (def-val def) '() 'need #f))))
653 (keep def? (ptset->list (var-sets var)))))
654 (varset->list vars)))
657 (define (pass2) ; transform non-definitions from top to bottom
658 (let loop ((lst1 ptrees) (lst2 '()))
660 (let ((ptree (car lst1)))
661 (cond ((not (core? (node-env ptree)))
663 (loop (cdr lst1) lst2))
665 (loop (cdr lst1) (cons ptree lst2)))
667 (loop (cdr lst1) (cons (br ptree
678 (define (br ptree substs reason expansion-limit)
681 (new-cst (node-source ptree) (node-env ptree)
685 (let ((var (ref-var ptree)))
686 (var-refs-set! var (ptset-remove (var-refs var) ptree))
687 (let ((new-var (var-subst var substs)))
688 (let ((x (var-to-val new-var substs)))
689 (if (and x (or (cst? x) (ref? x)))
691 (new-ref (node-source ptree) (node-env ptree)
694 ((set? ptree) ; variable guaranteed to be a global variable
695 (let ((var (set-var ptree))
696 (val (br (set-val ptree) substs 'need expansion-limit)))
697 (var-sets-set! var (ptset-remove (var-sets var) ptree))
698 (new-set (node-source ptree) (node-env ptree)
703 (let ((pre (br (tst-pre ptree) substs 'pred expansion-limit)))
705 (if (false-object? (cst-val pre))
708 (delete-ptree (tst-con ptree))
709 (br (tst-alt ptree) substs reason expansion-limit))
712 (delete-ptree (tst-alt ptree))
713 (br (tst-con ptree) substs reason expansion-limit)))
714 (new-tst (node-source ptree) (node-env ptree)
716 (br (tst-con ptree) substs reason expansion-limit)
717 (br (tst-alt ptree) substs reason expansion-limit)))))
720 (let ((pre (br (conj-pre ptree) substs reason expansion-limit)))
722 (if (false-object? (cst-val pre))
724 (delete-ptree (conj-alt ptree))
728 (br (conj-alt ptree) substs reason expansion-limit)))
729 (let ((alt (br (conj-alt ptree) substs reason expansion-limit)))
730 (cond ((and (cst? alt)
731 (false-object? (cst-val alt)))
732 (if (side-effects-impossible? pre)
738 ; (and X #f) => (begin X #f)
739 ; this transform should be generalized
740 (new-seq (node-source ptree) (node-env ptree)
744 (not (false-object? (cst-val alt)))
746 ; (if (and X non-#f) ...) => (if X ...)
750 (new-conj (node-source ptree) (node-env ptree)
755 (let ((pre (br (disj-pre ptree) substs reason expansion-limit)))
757 (if (false-object? (cst-val pre))
760 (br (disj-alt ptree) substs reason expansion-limit))
762 (delete-ptree (disj-alt ptree))
764 (let ((alt (br (disj-alt ptree) substs reason expansion-limit)))
766 (false-object? (cst-val alt)))
771 (new-disj (node-source ptree) (node-env ptree)
776 (new-prc (node-source ptree) (node-env ptree)
783 (br (prc-body ptree) substs 'need expansion-limit)))
786 (br-let ptree substs reason expansion-limit))
789 (let ((oper (app-oper ptree))
790 (args (app-args ptree)))
791 (if (or (cst? oper) (ref? oper))
792 (let ((br-oper (br oper substs 'need expansion-limit)))
793 ; at this point (or (cst? br-oper) (ref? br-oper))
794 (or (br-app-inline ptree br-oper args substs reason expansion-limit)
795 (br-app-simplify ptree br-oper args substs reason expansion-limit)))
796 (br-app ptree oper args substs reason expansion-limit))))
799 (new-fut (node-source ptree) (node-env ptree)
800 (br (fut-val ptree) substs 'need expansion-limit)))
803 (compiler-internal-error "br, unknown parse tree node type"))))
805 (define (var-subst var substs)
808 (let ((couple (car substs)))
809 (if (eq? (car couple) var)
810 (if (ref? (cdr couple))
811 (var-subst (ref-var (cdr couple)) (cdr substs))
813 (var-subst var (cdr substs))))))
815 (define (var-to-val var substs)
817 (global-single-def var)
818 (let ((x (assq var substs)))
821 (define (br-let? ptree)
823 (let ((oper (app-oper ptree))
824 (args (app-args ptree)))
825 (and (prc? oper) ; applying a lambda-expr is like a 'let'
826 (prc-req-and-opt-parms-only? oper)
827 (= (length (prc-parms oper)) (length args))))))
829 (define (br-app ptree oper args substs reason expansion-limit)
831 (if (and (br-let? oper)
832 (let ((body (prc-body (app-oper oper))))
835 (or (bound? (ref-var body))
836 (global-singly-bound? body))))))
838 ;; let-floating transformation when the code is of the
841 ;; ((let (...) var) E1 E2) -> (let (...) (var E1 E2))
843 (let ((proc (app-oper oper)))
844 (br (new-call (node-source oper) (node-env oper)
845 (new-prc (node-source proc) (node-env proc)
852 (new-call (node-source ptree) (node-env ptree)
860 (new-call (node-source ptree) (node-env ptree)
861 (br oper substs 'need expansion-limit)
862 (map (lambda (arg) (br arg substs 'need expansion-limit)) args))))
864 (define (br-let ptree substs reason expansion-limit)
876 (br-extend-substs vars vals substs))
878 (map (lambda (x) (br x new-substs 'need expansion-limit)) vals))
880 (br-extend-substs vars br-vals substs))
882 (br (prc-body proc) new-substs2 reason expansion-limit)))
884 (define (var->val var) (cdr (assq var var-val-map)))
886 (define (reachable-vars-from starting-point)
887 (let loop ((old-reachable-vars
893 (if (varset-equal? reachable-vars old-reachable-vars)
901 (bound-free-variables (var->val var))))
903 (varset-difference reachable-vars
904 old-reachable-vars)))))))))
906 ; remove useless bindings
908 (let ((reachable-vars
911 (cons (bound-free-variables new-body)
912 (map (lambda (br-val)
914 (varset-empty) ; reachable only if called
915 (bound-free-variables br-val)))
929 (if (and (not (varset-member? var reachable-vars))
934 (delete-ptree br-val)
942 (cons br-val new-vals)))))))))
944 (define (br-extend-substs vars vals substs)
952 (cond ((or (cst? val)
954 (or (bound? (ref-var val))
955 (global-singly-bound? val)))
957 (ptset-every? oper-pos? (var-refs var))))
960 (cons (cons var val) new-substs)))
966 (define (br-app-inline ptree br-oper args substs reason expansion-limit)
968 ; invariant: (or (cst? br-oper) (ref? br-oper))
971 (let* ((var (ref-var br-oper))
972 (val (var-to-val var substs)))
974 (define (inline-procedure new-expansion-limit)
975 (let ((cloned-oper (clone-ptree val)))
976 (delete-ptree br-oper)
977 (br-app ptree cloned-oper args substs reason
978 new-expansion-limit)))
982 (inline? (node-env val))
983 (if (and (bound? var)
984 (= (ptset-size (var-refs var)) 1)
985 (not (varset-member? var (bound-free-variables val))))
987 ; Procedure is referenced once and it is not direcly
988 ; recursive so inline it without changing the
989 ; expansion limit (the original code will be removed
992 (inline-procedure expansion-limit)
994 ; Procedure is referenced more than once or it is
995 ; directly recursive so we inline it only if we
996 ; don't exceed the expansion limit.
1003 (- (if expansion-limit
1004 (car expansion-limit)
1005 (quotient (* (inlining-limit (node-env ptree))
1009 (and (>= new-limit 0)
1012 (set-car! expansion-limit new-limit)
1013 (inline-procedure expansion-limit))
1014 (inline-procedure (list new-limit))))))))))
1016 (define (br-app-simplify ptree br-oper args substs reason expansion-limit)
1018 ; invariant: (or (cst? br-oper) (ref? br-oper))
1021 (map (lambda (arg) (br arg substs 'need expansion-limit)) args))
1023 (and (constant-fold? (node-env ptree))
1024 (specialize-app br-oper br-args (node-env ptree))))
1027 (nb-args-conforms? (length args) (proc-obj-call-pat proc))
1028 (proc-obj-simplify proc)))
1031 (simp ptree br-args))))
1032 (if simplified-ptree
1034 (delete-ptree br-oper)
1035 (for-each delete-ptree br-args)
1037 (new-call (node-source ptree) (node-env ptree)
1041 (define (ptree-size ptree)
1042 (let loop ((lst (node-children ptree)) (n 1))
1045 (loop (cdr lst) (+ n (ptree-size (car lst)))))))
1047 (define (side-effects-impossible? ptree)
1055 ((set? ptree) ; variable guaranteed to be a global variable
1059 (and (side-effects-impossible? (tst-pre ptree))
1060 (side-effects-impossible? (tst-con ptree))
1061 (side-effects-impossible? (tst-alt ptree))))
1064 (and (side-effects-impossible? (conj-pre ptree))
1065 (side-effects-impossible? (conj-alt ptree))))
1068 (and (side-effects-impossible? (disj-pre ptree))
1069 (side-effects-impossible? (disj-alt ptree))))
1075 (let ((oper (app-oper ptree))
1076 (args (app-args ptree)))
1077 (and (every? side-effects-impossible? args)
1078 (if (and (prc? oper) ; applying a lambda-expr is like a 'let'
1079 (prc-req-and-opt-parms-only? oper)
1080 (= (length (prc-parms oper)) (length args)))
1081 (side-effects-impossible? (prc-body oper))
1082 (let ((proc (app->specialized-proc ptree)))
1084 (not (proc-obj-side-effects? proc))))))))
1087 (side-effects-impossible? (fut-val ptree)))
1090 (compiler-internal-error "side-effects-impossible?, unknown parse tree node type"))))
1092 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1094 ;; Lambda-lifting procedure:
1095 ;; ------------------------
1097 ;; (lambda-lift lst) takes a list of parse-trees and returns a list
1098 ;; where each parse-tree has been modified so that some of its
1099 ;; procedures (i.e. lambda-expressions) are replaced with weaker ones
1100 ;; (i.e. lambda-expressions having fewer or no closed variables). It
1101 ;; is assumed that 'ptree' has already been assignment-converted. The
1102 ;; only procedures that are lambda-lifted are named procedures and
1103 ;; procedures which are passed to some primitive higher-order functions
1104 ;; (such as call-with-current-continuation).
1106 (define (lambda-lift lst)
1107 (for-each (lambda (ptree)
1108 (ll! ptree (varset-empty) '()))
1112 (define (ll! ptree cst-procs env)
1114 (define (new-env env vars)
1117 (let ((var (car l)))
1118 (cons (cons var (cons (ptset-size (var-refs var)) i))
1119 (loop (+ i 1) (cdr l))))
1121 (loop (length env) vars))
1123 (cond ((or (cst? ptree)
1126 (def? ptree) ; guaranteed to be a toplevel definition
1131 (for-each (lambda (child) (ll! child cst-procs env))
1132 (node-children ptree)))
1135 (ll! (prc-body ptree) cst-procs (new-env env (prc-parms ptree))))
1138 (let ((oper (app-oper ptree))
1139 (args (app-args ptree)))
1140 (if (and (prc? oper) ; applying a lambda-expr is like a 'let'
1141 (prc-req-and-opt-parms-only? oper)
1142 (= (length (prc-parms oper)) (length args)))
1143 (ll!-let ptree cst-procs (new-env env (prc-parms oper)))
1144 (ll!-call ptree cst-procs env))))
1147 (compiler-internal-error "ll!, unknown parse tree node type"))))
1149 (define (ll!-call ptree cst-procs env)
1151 (for-each (lambda (child) (ll! child cst-procs env))
1152 (node-children ptree))
1154 (let* ((oper (app-oper ptree))
1155 (proc (cond ((cst? oper) (cst-val oper))
1156 ((ref? oper) (global-proc-obj oper))
1158 (if (proc-obj? proc)
1160 (proc-obj-lift-pat proc))
1162 (modulo (quotient lift-pat 1000) 10))
1164 (modulo (quotient lift-pat 100) 10))
1165 (nb-req-and-opt-parms
1166 (modulo (quotient lift-pat 10) 10))
1168 (modulo lift-pat 10))
1173 (if (and (< 0 receiver-arg-pos)
1174 (<= min-nb-args nb-args))
1176 (list-ref args (- receiver-arg-pos 1))))
1177 (if (and (prc? receiver)
1178 (lambda-lift? (node-env receiver))
1179 (prc-req-and-opt-parms-only? receiver)
1180 (<= nb-req-and-opt-parms
1181 (length (prc-parms receiver)))
1182 (= (- (length (prc-parms receiver))
1183 nb-req-and-opt-parms)
1184 (- nb-args min-nb-args)))
1186 (ll-lifted-vars (bound-free-variables receiver)
1189 (if (and (not (null? vars))
1190 (<= (+ (length vars) (- nb-args min-nb-args))
1192 (let ((cloned-vars (clone-vars vars)))
1196 (define (new-ref* var)
1197 (new-ref (var-source var) (node-env ptree) var))
1202 (append (take args min-nb-args)
1204 (drop args min-nb-args))))
1206 ;; modify receiver procedure
1210 (append (take (prc-parms receiver)
1211 nb-req-and-opt-parms)
1213 (drop (prc-parms receiver)
1214 nb-req-and-opt-parms)))
1215 (for-each (lambda (x) (var-bound-set! x receiver))
1217 (node-fv-invalidate! receiver)
1218 (for-each (lambda (x y) (var-clone-set! x y))
1221 (ll-rename! receiver)
1222 (for-each (lambda (x) (var-clone-set! x #f))
1225 (define (ll!-let ptree cst-procs env)
1226 (let* ((proc (app-oper ptree))
1227 (vals (app-args ptree))
1228 (vars (prc-parms proc))
1229 (var-val-map (pair-up vars vals)))
1231 (define (var->val var) (cdr (assq var var-val-map)))
1233 (define (liftable-proc-vars vars)
1234 (let loop ((cst-proc-vars-list
1236 (let ((val (var->val var)))
1238 (lambda-lift? (node-env val))
1239 (ptset-every? oper-pos? (var-refs var)))))
1241 (let* ((cst-proc-vars
1242 (list->varset cst-proc-vars-list))
1243 (non-cst-proc-vars-list
1245 (let ((val (var->val var)))
1247 (not (varset-member? var cst-proc-vars)))))
1250 (list->varset non-cst-proc-vars-list))
1251 (cst-proc-vars-list*
1253 (not (varset-intersects?
1254 (bound-free-variables (var->val var))
1255 non-cst-proc-vars)))
1256 cst-proc-vars-list)))
1257 (if (= (length cst-proc-vars-list)
1258 (length cst-proc-vars-list*))
1260 (loop cst-proc-vars-list*)))))
1262 (define (transitively-closed-bound-free-variables vars)
1265 (cons var (bound-free-variables (var->val var))))
1268 (let ((changed? #f))
1269 (for-each (lambda (var-tcbfv)
1270 (let ((tcbfv (cdr var-tcbfv)))
1271 (let loop2 ((l (varset->list tcbfv))
1274 (if (not (= (varset-size fv)
1275 (varset-size tcbfv)))
1277 (set-cdr! var-tcbfv fv)
1278 (set! changed? #t)))
1279 (let ((x (assq (car l) tcbfv-map)))
1282 (varset-union fv (cdr x))
1290 (transitively-closed-bound-free-variables
1291 (liftable-proc-vars vars)))
1293 (map car tcbfv-map))
1295 (varset-union (list->varset cst-proc-vars-list) cst-procs)))
1297 (define (var->tcbfv var) (cdr (assq var tcbfv-map)))
1299 (define (lifted-vars var)
1300 (ll-lifted-vars (var->tcbfv var) cst-procs* env))
1302 (define (lift-app! var)
1303 (let* ((val (var->val var))
1304 (vars (lifted-vars var)))
1305 (if (not (null? vars))
1306 (for-each (lambda (oper)
1307 (let ((node (node-parent oper)))
1309 (define (new-ref* var)
1310 (new-ref (var-source var) (node-env node) var))
1312 (node-children-set! node
1313 (cons (app-oper node)
1314 (append (map new-ref* vars)
1315 (app-args node))))))
1316 (ptset->list (var-refs var))))))
1318 (define (lift-prc! var)
1319 (let* ((val (var->val var))
1320 (vars (lifted-vars var)))
1321 (if (not (null? vars))
1322 (let ((cloned-vars (clone-vars vars)))
1323 (prc-parms-set! val (append cloned-vars (prc-parms val)))
1324 (for-each (lambda (x) (var-bound-set! x val)) cloned-vars)
1325 (node-fv-invalidate! val)
1326 (for-each (lambda (x y) (var-clone-set! x y)) vars cloned-vars)
1328 (for-each (lambda (x) (var-clone-set! x #f)) vars)))))
1330 (for-each lift-app! cst-proc-vars-list)
1331 (for-each lift-prc! cst-proc-vars-list)
1332 (for-each (lambda (node) (ll! node cst-procs* env)) vals)
1333 (ll! (prc-body proc) cst-procs* env))))
1335 (define (ll-lifted-vars bfv cst-procs env)
1337 (define (order-vars vars)
1339 (sort-list (map (lambda (var) (assq var env)) vars)
1341 ;;;; (if (= (cadr x) (cadr y))
1342 ;;;; (< (cddr x) (cddr y))
1343 ;;;; (< (cadr x) (cadr y)))
1344 (< (cddr x) (cddr y))))))
1347 (varset->list (varset-difference bfv cst-procs))))
1349 (define (ll-rename! ptree)
1352 (let* ((var (ref-var ptree))
1353 (x (var-clone var)))
1356 (var-refs-set! var (ptset-remove (var-refs var) ptree))
1357 (var-refs-set! x (ptset-adjoin (var-refs x) ptree))
1358 (ref-var-set! ptree x)))))
1360 (node-fv-set! ptree #t)
1361 (node-bfv-set! ptree #t)
1363 (for-each (lambda (child) (ll-rename! child))
1364 (node-children ptree)))
1366 ;;;----------------------------------------------------------------------------
1370 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1372 ;; (parse-tree->expression ptree) returns the Scheme expression corresponding to
1373 ;; the parse tree 'ptree'.
1375 (define (parse-tree->expression ptree)
1376 (se ptree '() (list 0)))
1378 (define (se ptree env num)
1381 (let ((val (cst-val ptree)))
1385 (se-var->id (ref-var ptree) env))
1389 (se-var->id (set-var ptree) env)
1390 (se (set-val ptree) env num)))
1394 (se-var->id (def-var ptree) env)
1395 (se (def-val ptree) env num)))
1398 (list if-sym (se (tst-pre ptree) env num)
1399 (se (tst-con ptree) env num)
1400 (se (tst-alt ptree) env num)))
1403 (list and-sym (se (conj-pre ptree) env num)
1404 (se (conj-alt ptree) env num)))
1407 (list or-sym (se (disj-pre ptree) env num)
1408 (se (disj-alt ptree) env num)))
1411 (let ((new-env (se-rename ptree env num)))
1413 (se-parameters (prc-parms ptree)
1419 (se (prc-body ptree) new-env num))))
1422 (let ((oper (app-oper ptree))
1423 (args (app-args ptree)))
1424 (if (and (prc? oper) ; applying a lambda-expr is like a 'let'
1425 (prc-req-and-opt-parms-only? oper)
1426 (= (length (prc-parms oper)) (length args)))
1427 (let ((new-env (se-rename oper env num)))
1429 (if (varset-intersects?
1430 (list->varset (prc-parms oper))
1431 (varset-union-multi (map bound-free-variables args)))
1434 (se-bindings (prc-parms oper) args new-env num)
1435 (se (prc-body oper) new-env num)))
1436 (map (lambda (x) (se x env num)) (cons oper args)))))
1439 (list future-sym (se (fut-val ptree) env num)))
1442 (compiler-internal-error "se, unknown parse tree node type"))))
1444 (define use-actual-primitives-in-expression? #t)
1446 (define (se-constant val)
1447 (if (self-evaluating? val)
1451 (if use-actual-primitives-in-expression?
1452 (eval (string->symbol (proc-obj-name val)))
1453 (list '*primitive* (proc-obj-name val)))
1456 (define (se-var->id var env)
1457 (let ((id (let ((x (assq var env)))
1458 (if x (cdr x) (var-name var)))))
1461 ;; (string-append (symbol->string id)
1463 ;; (number->string (##object->serial-number var))))
1466 (define use-dotted-rest-parameter-when-possible? #t)
1468 (define (se-parameters parms opts keys rest? env num)
1470 (define (se-required parms n)
1473 (let ((parm (se-var->id (car parms) env)))
1474 (cons parm (se-required (cdr parms) (- n 1))))))
1476 (define (se-opts parms)
1478 (se-rest-and-keys parms)
1479 (cons optional-object
1480 (let loop ((parms parms) (opts opts))
1482 (se-rest-and-keys parms)
1483 (let ((parm (se-var->id (car parms) env)))
1484 (cons (list parm (se-constant (car opts)))
1485 (loop (cdr parms) (cdr opts)))))))))
1487 (define (se-rest-and-keys parms)
1489 (define (se-rest-at-end parm)
1490 (if use-dotted-rest-parameter-when-possible?
1492 (cons rest-object (cons parm '()))))
1495 (let ((parm (se-var->id (car (last-pair parms)) env)))
1497 (se-rest-at-end parm)
1498 (if (eq? rest? 'dsssl)
1499 (cons rest-object (cons parm (se-keys parms '())))
1500 (se-keys parms (se-rest-at-end parm)))))
1501 (se-keys parms '())))
1503 (define (se-keys parms tail)
1507 (let loop ((parms parms) (keys keys))
1510 (let ((parm (se-var->id (car parms) env)))
1511 (cons (list parm (se-constant (cdr (car keys))))
1512 (loop (cdr parms) (cdr keys)))))))))
1517 (if keys (length keys) 0)
1520 (define (se-bindings vars vals env num)
1523 (cons (list (se-var->id (car vars) env) (se (car vals) env num))
1524 (se-bindings (cdr vars) (cdr vals) env num))))
1526 (define (se-rename proc env num)
1530 (varset->list (free-variables (prc-body proc))))
1532 (map var-name parms))
1534 (map var-name free-vars))
1536 (append p-names fv-names))
1540 (define (conflict? var i)
1541 (let* ((p (pos-in-list var free-vars))
1542 (k (if p (+ p n) i)))
1543 (let loop ((lst names) (j 0))
1546 (let ((x (car lst)))
1547 (if (and (not (= i j))
1549 (eq? x (var-name var)))
1551 (loop (cdr lst) (+ j 1))))))))
1553 (define (rename vars i)
1556 (let* ((var (car vars))
1557 (id (var-name var)))
1559 (if (conflict? var i)
1561 (set-car! num (+ (car num) 1))
1563 (string-append (symbol->string id)
1565 (number->string (car num)))))
1567 (rename (cdr vars) (+ i 1))))))
1572 ;;; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1574 ;; C-interface stuff:
1576 (define (c-interface-begin module-name)
1577 (set! c-interface-module-name module-name)
1578 (set! c-interface-proc-count 0)
1579 (set! c-interface-obj-count 0)
1580 (set! c-interface-types scheme-to-c-notation)
1581 (set! c-interface-release-fns '())
1582 (set! c-interface-release-fn-count 0)
1583 (set! c-interface-converters '())
1584 (set! c-interface-converter-count 0)
1585 (set! c-interface-decls '())
1586 (set! c-interface-procs '())
1587 (set! c-interface-inits '())
1588 (set! c-interface-objs '())
1591 (define (c-interface-end)
1592 (let ((i (make-c-intf (reverse c-interface-decls)
1593 (reverse c-interface-procs)
1594 (reverse c-interface-inits)
1595 (reverse c-interface-objs))))
1596 (set! c-interface-module-name #f)
1597 (set! c-interface-proc-count #f)
1598 (set! c-interface-obj-count #f)
1599 (set! c-interface-types #f)
1600 (set! c-interface-release-fns #f)
1601 (set! c-interface-release-fn-count #f)
1602 (set! c-interface-converters #f)
1603 (set! c-interface-converter-count #f)
1604 (set! c-interface-decls #f)
1605 (set! c-interface-procs #f)
1606 (set! c-interface-inits #f)
1607 (set! c-interface-objs #f)
1610 (define c-interface-module-name #f)
1611 (define c-interface-proc-count #f)
1612 (define c-interface-obj-count #f)
1613 (define c-interface-types #f)
1614 (define c-interface-release-fns #f)
1615 (define c-interface-release-fn-count #f)
1616 (define c-interface-converters #f)
1617 (define c-interface-converter-count #f)
1618 (define c-interface-decls #f)
1619 (define c-interface-procs #f)
1620 (define c-interface-inits #f)
1621 (define c-interface-objs #f)
1623 (define (add-c-type name type)
1624 (set! c-interface-types
1625 (cons (cons name type) c-interface-types))
1628 (define (add-c-decl declaration-string)
1629 (set! c-interface-decls
1630 (cons declaration-string c-interface-decls))
1633 (define (add-c-proc c-proc)
1634 (set! c-interface-proc-count (+ c-interface-proc-count 1))
1635 (set! c-interface-procs
1636 (cons c-proc c-interface-procs))
1639 (define (add-c-init initialization-code-string)
1640 (set! c-interface-inits
1641 (cons initialization-code-string c-interface-inits))
1644 (define (add-c-obj obj)
1645 (set! c-interface-obj-count (+ c-interface-obj-count 1))
1646 (set! c-interface-objs
1647 (cons obj c-interface-objs))
1650 (define (make-c-intf decls procs inits objs) (vector decls procs inits objs))
1651 (define (c-intf-decls c-intf) (vector-ref c-intf 0))
1652 (define (c-intf-decls-set! c-intf x) (vector-set! c-intf 0 x))
1653 (define (c-intf-procs c-intf) (vector-ref c-intf 1))
1654 (define (c-intf-procs-set! c-intf x) (vector-set! c-intf 1 x))
1655 (define (c-intf-inits c-intf) (vector-ref c-intf 2))
1656 (define (c-intf-inits-set! c-intf x) (vector-set! c-intf 2 x))
1657 (define (c-intf-objs c-intf) (vector-ref c-intf 3))
1658 (define (c-intf-objs-set! c-intf x) (vector-set! c-intf 3 x))
1660 (define (make-c-proc scheme-name c-name arity body)
1661 (vector c-proc-tag scheme-name c-name arity body))
1663 (define c-proc-tag (list 'c-proc))
1667 (> (vector-length x) 0)
1668 (eq? (vector-ref x 0) c-proc-tag)))
1670 (define (c-proc-scheme-name x) (vector-ref x 1))
1671 (define (c-proc-c-name x) (vector-ref x 2))
1672 (define (c-proc-arity x) (vector-ref x 3))
1673 (define (c-proc-body x) (vector-ref x 4))
1675 (define (**c-define-type-expr? source)
1676 (and (match **c-define-type-sym -3 source)
1677 (or (let ((len (length (source-code source))))
1678 (and (or (= len 3) (= len 6))
1679 (proper-c-type-definition? source)))
1680 (ill-formed-special-form source))))
1682 (define (proper-c-type-definition? source)
1683 (let* ((code (source-code source))
1684 (name-source (cadr code))
1685 (name (source-code name-source)))
1686 (cond ((not (symbol-object? name))
1689 "C type's name must be an identifier"))
1690 ((assq name c-interface-types)
1693 "C type's name is already defined"))
1694 ((= (length code) 3)
1695 (let ((type-source (caddr code)))
1696 (check-c-type type-source #f #t))) ; allow all types
1698 (let* ((ctype-source (caddr code))
1699 (ctype (source-code ctype-source))
1700 (ctos-source (cadddr code))
1701 (ctos (source-code ctos-source))
1702 (stoc-source (cadddr (cdr code)))
1703 (stoc (source-code stoc-source))
1704 (cleanup-source (cadddr (cddr code)))
1705 (cleanup (source-code cleanup-source)))
1706 (cond ((not (string? ctype))
1709 "Second argument to 'c-define-type' must be a string"))
1710 ((not (string? ctos))
1713 "Third argument to 'c-define-type' must be a string"))
1714 ((not (valid-c-or-c++-function-id? ctos))
1717 "Ill-formed C function identifier"))
1718 ((not (string? stoc))
1721 "Fourth argument to 'c-define-type' must be a string"))
1722 ((not (valid-c-or-c++-function-id? stoc))
1725 "Ill-formed C function identifier"))
1726 ((not (or (false-object? cleanup)
1730 "Fifth argument to 'c-define-type' must be a boolean"))
1734 (define (c-type-definition-name source)
1735 (let ((code (source-code source)))
1738 (define (c-type-definition-type source)
1739 (let ((code (source-code source)))
1740 (if (= (length code) 3)
1744 (source-code (caddr code))
1745 (source-code (cadddr code))
1746 (source-code (cadddr (cdr code)))
1747 (source-code (cadddr (cddr code)))))))
1749 (define (**c-declare-expr? source)
1750 (and (match **c-declare-sym 2 source)
1751 (let ((code (source-code source)))
1752 (or (string? (source-code (cadr code)))
1755 "Argument to 'c-declare' must be a string")))))
1757 (define (c-declaration-body source)
1758 (cadr (source-code source)))
1760 (define (**c-initialize-expr? source)
1761 (and (match **c-initialize-sym 2 source)
1762 (let ((code (source-code source)))
1763 (or (string? (source-code (cadr code)))
1766 "Argument to 'c-initialize' must be a string")))))
1768 (define (c-initialization-body source)
1769 (cadr (source-code source)))
1771 (define (**c-lambda-expr? source)
1772 (and (match **c-lambda-sym 4 source)
1773 (let ((code (source-code source)))
1774 (if (not (string? (source-code (cadddr code))))
1777 "Third argument to 'c-lambda' must be a string")
1778 (check-c-function-type (cadr code) (caddr code) #f)))))
1780 (define (**c-define-expr? source env)
1781 (and (match **c-define-sym -7 source)
1782 (proper-c-definition? source env)))
1784 (define (proper-c-definition? source env)
1785 (let* ((code (source-code source))
1786 (pattern-source (cadr code))
1787 (pattern (source-code pattern-source))
1788 (arg-typs-source (caddr code))
1789 (res-typ-source (cadddr code))
1790 (name-source (car (cddddr code)))
1791 (name (source-code name-source))
1792 (scope-source (cadr (cddddr code)))
1793 (scope (source-code scope-source)))
1794 (cond ((not (pair? pattern))
1797 "Ill-formed definition pattern"))
1798 ((not (bindable-var? (car pattern) env))
1801 "Procedure name must be an identifier"))
1803 (and (check-c-function-type arg-typs-source res-typ-source #f)
1804 (cond ((not (string? name))
1807 "Fourth argument to 'c-define' must be a string"))
1808 ((not (valid-c-or-c++-function-id? name))
1811 "Ill-formed C function identifier"))
1812 ((not (string? scope))
1815 "Fifth argument to 'c-define' must be a string"))
1819 (define (c-definition-name source)
1820 (let ((code (source-code source)))
1821 (car (source-code (cadr code)))))
1823 (define (c-definition-value source)
1824 (let ((code (source-code source))
1825 (loc (source-locat source)))
1827 (cons (make-source **lambda-sym loc)
1828 (cons (parms->source (cdr (source-code (cadr code))) loc)
1829 (cdr (cddddr code))))
1832 (define (c-definition-param-types source)
1833 (source-code (caddr (source-code source))))
1835 (define (c-definition-result-type source)
1836 (cadddr (source-code source)))
1838 (define (c-definition-proc-name source)
1839 (car (cddddr (source-code source))))
1841 (define (c-definition-scope source)
1842 (cadr (cddddr (source-code source))))
1844 (define (c-type-pt-syntax-error source err-source msg . args)
1845 (apply pt-syntax-error (cons (or err-source source) (cons msg args))))
1847 (define (check-c-function-type arg-typs-source res-typ-source err-source)
1848 (and (check-c-arg-types arg-typs-source err-source)
1849 (check-c-result-type res-typ-source err-source)))
1851 (define (check-c-arg-types arg-typs-source err-source)
1852 (let ((arg-typs (source-code arg-typs-source)))
1853 (if (not (proper-length arg-typs))
1854 (c-type-pt-syntax-error
1857 "Ill-terminated C function argument type list")
1858 (let loop ((lst arg-typs))
1860 (and (check-c-type (car lst) err-source #f) ; void not allowed
1864 (define (check-c-result-type res-typ-source err-source)
1865 (check-c-type res-typ-source err-source #t)) ; allow all types
1867 (define (check-c-type typ-source err-source void-allowed?)
1869 (define (ill-formed-c-type)
1870 (c-type-pt-syntax-error typ-source err-source "Ill-formed C type"))
1872 (let ((typ (source-code typ-source)))
1874 (let ((len (proper-length (cdr typ))))
1876 (let ((head (source-code (car typ))))
1878 (define (check pointer? err-msg)
1881 (let* ((x-source (cadr typ))
1882 (x (source-code x-source)))
1887 #t) ; allow all types
1889 (valid-c-or-c++-type-id? x))))
1891 (let ((tag (source-code (caddr typ))))
1892 (or (false-object? tag)
1893 (symbol-object? tag)
1902 (let ((id (source-code (cadddr typ))))
1903 (or (false-object? id)
1905 (valid-c-or-c++-function-id? id))))))
1906 (c-type-pt-syntax-error
1911 (define (check-function err-msg)
1913 (check-c-function-type
1917 (c-type-pt-syntax-error
1922 (cond ((eq? head struct-sym)
1923 (check #f "Ill-formed C STRUCT type"))
1924 ((eq? head union-sym)
1925 (check #f "Ill-formed C UNION type"))
1926 ((eq? head type-sym)
1927 (check #f "Ill-formed C TYPE type"))
1928 ((eq? head pointer-sym)
1929 (check #t "Ill-formed C POINTER type"))
1930 ((eq? head nonnull-pointer-sym)
1931 (check #t "Ill-formed C NONNULL POINTER type"))
1932 ((eq? head function-sym)
1933 (check-function "Ill-formed C FUNCTION type"))
1934 ((eq? head nonnull-function-sym)
1935 (check-function "Ill-formed C NONNULL FUNCTION type"))
1937 (ill-formed-c-type))))
1939 (c-type-pt-syntax-error
1942 "Ill-terminated C type"))))
1944 (or (valid-c-or-c++-type-id? typ)
1945 (c-type-pt-syntax-error
1948 "Ill-formed C type identifier")))
1949 ((symbol-object? typ)
1950 (if (eq? typ void-sym)
1952 (c-type-pt-syntax-error
1955 "Ill-placed C VOID type"))
1956 (let ((x (assq typ c-interface-types)))
1958 (let ((def (cdr x)))
1959 (case (vector-ref def 0)
1967 (c-type-pt-syntax-error
1970 "Undefined C type identifier:"
1973 (ill-formed-c-type)))))
1975 (define (resolve-type typ-source)
1976 (let ((typ (source-code typ-source)))
1977 (if (symbol-object? typ)
1978 (let ((x (assq typ c-interface-types)))
1980 (let ((def (cdr x)))
1981 (if (eq? (vector-ref def 0) 'alias)
1982 (resolve-type (vector-ref def 1))
1987 (define (void-type? typ-source)
1988 (eq? (source-code (resolve-type typ-source)) void-sym))
1990 (define (scmobj-type? typ-source)
1991 (eq? (source-code (resolve-type typ-source)) scheme-object-sym))
1993 (define (type-needs-cleanup? typ-source)
1994 (let ((typ (source-code typ-source)))
1996 (let ((head (source-code (car typ))))
1997 (or (eq? head struct-sym)
1998 (eq? head union-sym)
2000 (eq? head function-sym)
2001 (eq? head nonnull-function-sym))))
2004 ((symbol-object? typ)
2005 (let ((x (assq typ c-interface-types)))
2007 (let ((def (cdr x)))
2008 (case (vector-ref def 0)
2012 (type-needs-cleanup? (vector-ref def 1)))))
2017 (define (type-accessed-indirectly? typ-source)
2018 (let ((typ (source-code typ-source)))
2020 (let ((head (source-code (car typ))))
2021 (cond ((eq? head struct-sym)
2022 (vector "STRUCT" (source-code (cadr typ))))
2023 ((eq? head union-sym)
2024 (vector "UNION" (source-code (cadr typ))))
2025 ((eq? head type-sym)
2026 (vector "TYPE" (source-code (cadr typ))))
2027 ((eq? head pointer-sym)
2029 ((eq? head nonnull-pointer-sym)
2030 '#("NONNULLPOINTER" #f))
2031 ((eq? head function-sym)
2033 ((eq? head nonnull-function-sym)
2034 '#("NONNULLFUNCTION" #f))
2038 (vector "TYPE" typ))
2039 ((symbol-object? typ)
2040 (let ((x (assq typ c-interface-types)))
2042 (let ((def (cdr x)))
2043 (case (vector-ref def 0)
2047 (type-accessed-indirectly? (vector-ref def 1)))))
2052 (define (pt-c-lambda source env use)
2055 (c-lambda-param-types source)
2056 (c-lambda-result-type source)
2057 (source-code (c-lambda-proc-name source)))))
2060 (env-lookup-global-var env (string->symbol name)))))
2062 (define (c-lambda-param-types source)
2063 (source-code (cadr (source-code source))))
2065 (define (c-lambda-result-type source)
2066 (caddr (source-code source)))
2068 (define (c-lambda-proc-name source)
2069 (cadddr (source-code source)))
2071 (define (number-from-1 lst)
2072 (let loop ((i 1) (lst1 lst) (lst2 '()))
2074 (loop (+ i 1) (cdr lst1) (cons (cons (car lst1) i) lst2))
2077 (define (c-type-converter to-scmobj? typ from to)
2080 (compiler-internal-error "c-type-converter, unknown C type"))
2082 (define (convert kind name tag id)
2084 (if (false-object? tag)
2085 (string-append c-id-prefix "FAL")
2086 (let* ((tag-list (if (symbol-object? tag) (list tag) tag))
2087 (x (object-pos-in-list tag-list c-interface-objs)))
2093 (- (- c-interface-obj-count x) 1)
2094 (let ((n c-interface-obj-count))
2095 (add-c-obj tag-list)
2100 (cond ((eq? kind pointer-sym)
2101 "POINTER_TO_SCMOBJ(")
2102 ((eq? kind nonnull-pointer-sym)
2103 "NONNULLPOINTER_TO_SCMOBJ(")
2106 (cond ((eq? kind struct-sym)
2107 "STRUCT_TO_SCMOBJ(")
2108 ((eq? kind union-sym)
2114 from "_voidstar," tag-str ","
2115 (if (false-object? id)
2116 (if (or (eq? kind pointer-sym)
2117 (eq? kind nonnull-pointer-sym))
2124 (assoc descr c-interface-release-fns)))
2128 c-interface-release-fn-count)
2133 (number->string i))))
2134 (set! c-interface-release-fn-count
2136 (set! c-interface-release-fns
2137 (cons (cons descr release-fn)
2138 c-interface-release-fns))
2142 (cond ((eq? kind struct-sym)
2143 "DEF_RELEASE_FN_STRUCT(")
2144 ((eq? kind union-sym)
2145 "DEF_RELEASE_FN_UNION(")
2147 "DEF_RELEASE_FN_TYPE("))
2157 (cond ((eq? kind pointer-sym)
2158 "SCMOBJ_TO_POINTER(")
2159 ((eq? kind nonnull-pointer-sym)
2160 "SCMOBJ_TO_NONNULLPOINTER(")
2163 (cond ((eq? kind struct-sym)
2164 "SCMOBJ_TO_STRUCT(")
2165 ((eq? kind union-sym)
2171 from "," to "_voidstar," tag-str))))
2173 (let ((t (source-code typ)))
2175 (let ((head (source-code (car t)))
2176 (len (length (cdr t))))
2177 (cond ((or (eq? head struct-sym)
2178 (eq? head union-sym)
2180 (eq? head pointer-sym)
2181 (eq? head nonnull-pointer-sym))
2184 (source-code (cadr t))
2186 (source->expression (caddr t))
2187 (string->symbol (c-type-decl typ "")))
2189 (source-code (cadddr t))
2191 ((or (eq? head function-sym)
2192 (eq? head nonnull-function-sym))
2195 (if (eq? head function-sym)
2196 "FUNCTION_TO_SCMOBJ("
2197 "NONNULLFUNCTION_TO_SCMOBJ(")
2198 from "_voidstar," to)
2200 (fn-param-converter typ)))
2202 (if (eq? head function-sym)
2203 "SCMOBJ_TO_FUNCTION("
2204 "SCMOBJ_TO_NONNULLFUNCTION(")
2205 from "," converter "," to "_voidstar"))))
2215 (let ((x (assq t c-interface-types)))
2217 (let ((def (cdr x)))
2218 (case (vector-ref def 0)
2237 (define nl-str (string #\newline))
2239 (define (c-preproc-define id val body)
2241 "#define " id " " val nl-str
2243 "#undef " id nl-str))
2245 (define (c-preproc-define-default-empty id body)
2249 "#ifndef " id nl-str
2250 "#define " id nl-str
2253 (define (c-result sfun? scheme-side?)
2257 (if sfun? "SFUN_RESULT" "CFUN_RESULT")
2260 (define (c-argument scheme-side? numbered-typ)
2261 (let ((i (number->string (cdr numbered-typ))))
2264 (if scheme-side? "ARG" "arg")
2267 (define (c-declare-argument sfun? numbered-typ body)
2268 (let* ((c-id (c-argument #f numbered-typ))
2269 (scm-id (c-argument #t numbered-typ))
2270 (typ (car numbered-typ))
2271 (i (number->string (cdr numbered-typ)))
2272 (scmobj? (scmobj-type? typ))
2273 (indirect-access (type-accessed-indirectly? typ)))
2277 (if sfun? "BEGIN_SFUN_ARG_SCMOBJ(" "BEGIN_CFUN_ARG_SCMOBJ(")
2278 (if sfun? "BEGIN_SFUN_ARG(" "BEGIN_CFUN_ARG("))
2287 (string-append "void* " c-id "_voidstar")
2288 (c-type-decl typ c-id)))))
2292 (if (vector-ref indirect-access 1)
2295 (vector-ref indirect-access 0)
2297 (vector-ref indirect-access 1)
2303 c-id-prefix "BEGIN_SFUN_COPY_" tail
2305 c-id-prefix "END_SFUN_COPY_" tail))
2307 (string-append c-id "_voidstar")
2308 (string-append c-id-prefix "SFUN_CAST(void*," c-id ")")
2314 (if (vector-ref indirect-access 1)
2316 "CFUN_CAST_AND_DEREF("
2317 (c-type-decl typ "*"))
2320 (c-type-decl typ "")))
2327 (if sfun? "END_SFUN_ARG_SCMOBJ(" "END_CFUN_ARG_SCMOBJ(")
2328 (if sfun? "END_SFUN_ARG(" "END_CFUN_ARG("))
2331 (define (c-convert-representation sfun? to-scmobj? typ from to i body)
2334 (c-type-converter to-scmobj? typ from to)
2335 (if i (string-append "," i) "")
2338 c-id-prefix (if sfun? "BEGIN_SFUN_" "BEGIN_CFUN_") tail
2340 c-id-prefix (if sfun? "END_SFUN_" "END_CFUN_") tail)))
2342 (define (c-convert-argument sfun? numbered-typ body)
2346 (c-argument (not sfun?) numbered-typ))
2348 (c-argument sfun? numbered-typ))
2350 (number->string (cdr numbered-typ)))
2355 (if (scmobj-type? typ)
2356 (c-preproc-define to from body)
2357 (c-convert-representation sfun? sfun? typ from to i body)))))
2369 (define (c-set-result sfun? result-typ)
2370 (cond ((void-type? result-typ)
2373 (if sfun? "SFUN_SET_RESULT_VOID" "CFUN_SET_RESULT_VOID")
2375 ((scmobj-type? result-typ)
2378 (if sfun? "SFUN_SET_RESULT_SCMOBJ" "CFUN_SET_RESULT_SCMOBJ")
2381 (c-convert-representation
2385 (c-result sfun? sfun?)
2386 (c-result sfun? (not sfun?))
2390 (if sfun? "SFUN_SET_RESULT" "CFUN_SET_RESULT")
2393 (define (c-make-function sfun? param-typs result-typ make-body)
2395 (not (every? (lambda (t) (not (type-needs-cleanup? t)))
2398 (define (convert-param-list)
2400 (define (scmobj-typ? numbered-typ)
2401 (scmobj-type? (car numbered-typ)))
2403 (define (not-scmobj-typ? numbered-typ)
2404 (not (scmobj-typ? numbered-typ)))
2406 (let ((numbered-param-typs (number-from-1 param-typs)))
2407 (let convert ((numbered-typs
2408 (append (keep scmobj-typ? numbered-param-typs)
2409 (keep not-scmobj-typ? numbered-param-typs))))
2410 (if (null? numbered-typs)
2411 (make-body (c-set-result sfun? result-typ) cleanup?)
2415 (convert (cdr numbered-typs)))))))
2419 (string-append c-id-prefix "NARGS")
2421 (number->string (length param-typs))
2423 (if (void-type? result-typ)
2434 (convert-param-list)
2438 (if cleanup? "CFUN_ERROR_CLEANUP_VOID" "CFUN_ERROR_VOID"))
2441 (c-set-result sfun? result-typ)
2444 (if sfun? "END_SFUN_VOID" "END_CFUN_VOID") nl-str)
2447 (c-result sfun? #f))
2449 (scmobj-type? result-typ))
2450 (indirect-access-result
2451 (type-accessed-indirectly? result-typ))
2458 "BEGIN_SFUN_SCMOBJ("
2461 "BEGIN_CFUN_SCMOBJ")
2469 (if indirect-access-result
2470 (string-append "void* " c-id "_voidstar"
2471 (if sfun? " = 0" ""))
2472 (c-type-decl result-typ c-id))
2475 (convert-param-list)
2480 (if cleanup? "CFUN_ERROR_CLEANUP_SCMOBJ" "CFUN_ERROR_SCMOBJ"))
2483 (if cleanup? "CFUN_ERROR_CLEANUP" "CFUN_ERROR")))
2486 (c-set-result sfun? result-typ)
2490 (if sfun? "END_SFUN_SCMOBJ" "END_CFUN_SCMOBJ")
2491 (if sfun? "END_SFUN" "END_CFUN"))
2494 (string-append "return " c-id ";" nl-str)
2496 (if indirect-access-result
2501 (if (vector-ref indirect-access-result 1)
2503 (if sfun? "SFUN_CAST_AND_DEREF(" "CFUN_CAST_AND_DEREF(")
2504 (c-type-decl result-typ "*"))
2506 (if sfun? "SFUN_CAST(" "CFUN_CAST(")
2507 (c-type-decl result-typ "")))
2513 (define (comma-separated strs)
2518 (apply string-append
2519 (map (lambda (s) (string-append "," s)) (cdr strs))))))
2521 (define (c-type-decl typ inner)
2524 (compiler-internal-error "c-type-decl, unknown C type"))
2526 (define (prefix-inner str)
2527 (if (and (> (string-length inner) 0)
2528 (c-id-subsequent? (string-ref inner 0)))
2529 (string-append str " " inner)
2530 (string-append str inner)))
2532 (let ((t (source-code typ)))
2534 (let ((head (source-code (car t))))
2535 (cond ((eq? head struct-sym)
2537 (string-append "struct " (source-code (cadr t)))))
2538 ((eq? head union-sym)
2540 (string-append "union " (source-code (cadr t)))))
2541 ((eq? head type-sym)
2543 (source-code (cadr t))))
2544 ((or (eq? head pointer-sym)
2545 (eq? head nonnull-pointer-sym))
2546 (c-type-decl (cadr t)
2547 (string-append "*" inner)))
2548 ((or (eq? head function-sym)
2549 (eq? head nonnull-function-sym))
2550 (c-type-decl (caddr t)
2553 (c-param-list-with-types
2554 (source-code (cadr t))))))
2560 (let ((x (assq t c-interface-types)))
2562 (let ((def (cdr x)))
2563 (case (vector-ref def 0)
2565 (prefix-inner (vector-ref def 1)))
2567 (c-type-decl (vector-ref def 1) inner))))
2572 (define (c-param-list-with-types typs)
2574 (string-append c-id-prefix "PVOID")
2578 (comma-separated (map (lambda (typ) (c-type-decl typ "")) typs))
2581 (define (c-param-id numbered-typ)
2582 (c-argument #f numbered-typ))
2584 (define (c-param-list-with-ids numbered-typs)
2585 (if (null? numbered-typs)
2586 (string-append c-id-prefix "PVOID")
2591 (map (lambda (t) (c-type-decl (car t) (c-param-id t)))
2594 (comma-separated (map c-param-id numbered-typs))
2596 (apply string-append
2600 (c-type-decl (car t) (c-param-id t))
2605 (define (c-function-decl param-typs result-typ id scope body)
2606 (let ((numbered-typs (number-from-1 param-typs)))
2607 (let ((function-decl
2608 (c-type-decl result-typ
2613 (c-param-list-with-ids numbered-typs)
2614 (c-param-list-with-types param-typs))))))
2618 function-decl nl-str
2619 "{" nl-str body "}" nl-str)
2621 function-decl ";" nl-str)))))
2623 (define (c-function param-typs result-typ proc-name c-defined? scope)
2627 c-id-prefix "MLBL(" c-id-prefix "C_LBL_" proc-name ")")
2629 c-id-prefix "FAL"))))
2631 (define (make-body set-result-code cleanup?)
2633 c-id-prefix "BEGIN_SFUN_BODY" nl-str
2634 (let convert ((numbered-typs (number-from-1 param-typs)))
2635 (if (null? numbered-typs)
2638 (cond ((void-type? result-typ)
2640 ((scmobj-type? result-typ)
2645 (let ((numbered-typ (car numbered-typs)))
2649 (number->string (cdr numbered-typ))
2651 (c-argument #t numbered-typ)
2653 (convert (cdr numbered-typs))))))
2655 c-id-prefix "END_SFUN_BODY" nl-str))
2658 (c-function-decl param-typs
2662 (c-make-function proc-val
2667 (define (fn-param-converter typ)
2668 (let ((function-c-type (c-type-decl typ "")))
2669 (cond ((assoc function-c-type c-interface-converters)
2676 (source-code (cadr t)))
2680 c-interface-converter-count)
2685 (number->string i))))
2686 (set! c-interface-converter-count
2688 (set! c-interface-converters
2689 (cons (cons function-c-type converter)
2690 c-interface-converters))
2696 (string-append c-id-prefix "LOCAL"))
2699 (define (build-c-define param-typs result-typ proc-name scope)
2700 (c-function param-typs result-typ proc-name #t scope))
2702 (define (strip-param-typs param-typs)
2703 param-typs);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2705 (define (build-c-lambda param-typs result-typ proc-name)
2707 (number->string c-interface-proc-count))
2709 (string-append module-prefix c-interface-module-name "#" index))
2711 (string-append c-id-prefix (scheme-id->c-id scheme-name)))
2713 (length param-typs))
2714 (stripped-param-typs
2715 (strip-param-typs param-typs)))
2717 (define (make-body set-result-code cleanup?)
2720 (if cleanup? "BEGIN_CFUN_BODY_CLEANUP" "BEGIN_CFUN_BODY")
2722 (c-preproc-define-default-empty
2723 (string-append c-id-prefix "AT_END")
2725 (if (valid-c-or-c++-function-id? proc-name)
2728 (indirect-access-result
2729 (type-accessed-indirectly? result-typ))
2734 (map c-param-id (number-from-1 stripped-param-typs)))
2736 (cond ((void-type? result-typ)
2742 (indirect-access-result
2743 (if (vector-ref indirect-access-result 1)
2747 (vector-ref indirect-access-result 0)
2749 (vector-ref indirect-access-result 1)
2757 (vector-ref indirect-access-result 0)
2773 (if cleanup? "END_CFUN_BODY_CLEANUP" "END_CFUN_BODY")
2777 (make-c-proc scheme-name
2786 (define (scheme-id->c-id s)
2787 (let loop1 ((i (- (string-length s) 1)) (lst '()))
2789 (let ((c (string-ref s i)))
2790 (cond ((char=? c #\_)
2791 (loop1 (- i 1) (cons c (cons c lst))))
2792 ((c-id-subsequent? c)
2793 (loop1 (- i 1) (cons c lst)))
2795 (let ((n (character->unicode c)))
2797 (loop1 (- i 1) (cons #\_ (cons #\0 (cons #\_ lst))))
2798 (let loop2 ((n n) (lst (cons #\_ lst)))
2800 (loop2 (quotient n 16)
2801 (cons (string-ref "0123456789abcdef"
2804 (loop1 (- i 1) (cons #\_ lst)))))))))
2807 (define (c-id-initial? c) ; c is one of #\A..#\Z, #\a..#\z, #\_
2808 (let ((n (character->unicode c)))
2809 (or (and (>= n 65) (<= n 90))
2810 (and (>= n 97) (<= n 122))
2813 (define (c-id-subsequent? c) ; c is one of #\A..#\Z, #\a..#\z, #\_, #\0..#\9
2814 (let ((n (character->unicode c)))
2815 (or (and (>= n 65) (<= n 90))
2816 (and (>= n 97) (<= n 122))
2818 (and (>= n 48) (<= n 57)))))
2820 (define (valid-c-id? id type?)
2821 (let ((n (string-length id)))
2823 (c-id-initial? (string-ref id 0))
2824 (let loop ((i 1) (depth 0))
2826 (let ((c (string-ref id i)))
2827 (cond ((and (< (+ i 2) n)
2829 (char=? #\: (string-ref id (+ i 1)))
2830 (c-id-initial? (string-ref id (+ i 2))))
2831 (loop (+ i 3) depth))
2835 (c-id-initial? (string-ref id (+ i 1))))
2836 (loop (+ i 2) (+ depth 1)))
2839 (c-id-initial? (string-ref id (+ i 1)))
2841 (loop (+ i 2) depth))
2842 ((and (char=? #\> c)
2844 (loop (+ i 1) (- depth 1)))
2845 ((c-id-subsequent? c)
2846 (loop (+ i 1) depth))
2851 (define (valid-c-or-c++-function-id? id)
2852 (valid-c-id? id #f))
2854 (define (valid-c-or-c++-type-id? id)
2855 (valid-c-id? id #t))
2857 ;;;============================================================================