1#| -*-Scheme-*- 2 3Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 4 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 5 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Massachusetts 6 Institute of Technology 7 8This file is part of MIT/GNU Scheme. 9 10MIT/GNU Scheme is free software; you can redistribute it and/or modify 11it under the terms of the GNU General Public License as published by 12the Free Software Foundation; either version 2 of the License, or (at 13your option) any later version. 14 15MIT/GNU Scheme is distributed in the hope that it will be useful, but 16WITHOUT ANY WARRANTY; without even the implied warranty of 17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18General Public License for more details. 19 20You should have received a copy of the GNU General Public License 21along with MIT/GNU Scheme; if not, write to the Free Software 22Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 23USA. 24 25|# 26 27;;;; SCode Optimizer: Expression analysis 28;;; package: (scode-optimizer analyze) 29 30(declare (usual-integrations) 31 (integrate-external "object")) 32 33;;; EXPRESSION/ALWAYS-FALSE? 34 35;; True iff expression can be shown to always return #F. 36;; That is, the expression counts as #f to a conditional. 37;; Expression is not shown to be side-effect free. 38(declare (integrate-operator expression/always-false?)) 39(define (expression/always-false? expression) 40 ((expression/method always-false?-dispatch-vector expression) expression)) 41 42(define always-false?-dispatch-vector 43 (expression/make-dispatch-vector)) 44 45(define define-method/always-false? 46 (expression/make-method-definer always-false?-dispatch-vector)) 47 48(define-method/always-false? 'ACCESS false-procedure) 49 50(define-method/always-false? 'ASSIGNMENT false-procedure) 51 52(define-method/always-false? 'COMBINATION 53 (lambda (expression) 54 (cond ((expression/call-to-not? expression) 55 (expression/never-false? (first (combination/operands expression)))) 56 ((procedure? (combination/operator expression)) 57 (expression/always-false? (procedure/body (combination/operator expression)))) 58 (else #f)))) 59 60(define-method/always-false? 'CONDITIONAL 61 (lambda (expression) 62 (and (or (expression/always-false? (conditional/predicate expression)) 63 (expression/always-false? (conditional/consequent expression))) 64 (or (expression/never-false? (conditional/predicate expression)) 65 (expression/always-false? (conditional/alternative expression)))))) 66 67(define-method/always-false? 'CONSTANT 68 (lambda (expression) 69 (not (constant/value expression)))) 70 71(define-method/always-false? 'DECLARATION 72 (lambda (expression) 73 (expression/always-false? 74 (declaration/expression expression)))) 75 76;; A promise is not a false value. 77(define-method/always-false? 'DELAY false-procedure) 78 79(define-method/always-false? 'DISJUNCTION 80 (lambda (expression) 81 (and (expression/always-false? (disjunction/predicate expression)) 82 (expression/always-false? (disjunction/alternative expression))))) 83 84(define-method/always-false? 'OPEN-BLOCK 85 (lambda (expression) 86 (expression/always-false? 87 (last (open-block/actions expression))))) 88 89;; A closure is not a false value. 90(define-method/always-false? 'PROCEDURE false-procedure) 91 92(define-method/always-false? 'QUOTATION false-procedure) 93 94(define-method/always-false? 'REFERENCE false-procedure) 95 96(define-method/always-false? 'SEQUENCE 97 (lambda (expression) 98 (expression/always-false? 99 (last (sequence/actions expression))))) 100 101(define-method/always-false? 'THE-ENVIRONMENT false-procedure) 102 103;;; EXPRESSION/BOOLEAN? 104;; 105;; T if expression can be shown to return only #T or #F. 106;; 107(declare (integrate-operator expression/boolean?)) 108(define (expression/boolean? expression) 109 ((expression/method boolean?-dispatch-vector expression) expression)) 110 111(define boolean?-dispatch-vector 112 (expression/make-dispatch-vector)) 113 114(define define-method/boolean? 115 (expression/make-method-definer boolean?-dispatch-vector)) 116 117(define-method/boolean? 'ACCESS false-procedure) 118 119(define-method/boolean? 'ASSIGNMENT false-procedure) 120 121(define-method/boolean? 'COMBINATION 122 (lambda (expression) 123 (or (expression/call-to-boolean-predicate? expression) 124 (and (procedure? (combination/operator expression)) 125 (boolean? (procedure/body (combination/operator expression))))))) 126 127(define-method/boolean? 'CONDITIONAL 128 (lambda (expression) 129 (and (or (expression/always-false? (conditional/predicate expression)) 130 (expression/boolean? (conditional/consequent expression))) 131 (or (expression/never-false? (conditional/predicate expression)) 132 (expression/boolean? (conditional/alternative expression)))))) 133 134(define-method/boolean? 'CONSTANT 135 (lambda (expression) 136 ;; jrm: do not accept unspecific here. 137 (or (not (constant/value expression)) 138 (eq? (constant/value expression) #t)))) 139 140(define-method/boolean? 'DECLARATION 141 (lambda (expression) 142 (expression/boolean? (declaration/expression expression)))) 143 144(define-method/boolean? 'DELAY false-procedure) 145 146(define-method/boolean? 'DISJUNCTION 147 (lambda (expression) 148 (and (expression/boolean? (disjunction/predicate expression)) 149 (or (expression/never-false? (disjunction/predicate expression)) 150 (expression/boolean? (disjunction/alternative expression)))))) 151 152(define-method/boolean? 'OPEN-BLOCK 153 (lambda (expression) 154 (expression/boolean? 155 (last (open-block/actions expression))))) 156 157(define-method/boolean? 'PROCEDURE false-procedure) 158 159(define-method/boolean? 'QUOTATION false-procedure) 160 161(define-method/boolean? 'REFERENCE false-procedure) 162 163(define-method/boolean? 'SEQUENCE 164 (lambda (expression) 165 (expression/boolean? (last (sequence/actions expression))))) 166 167(define-method/boolean? 'THE-ENVIRONMENT false-procedure) 168 169;;; EXPRESSION/EFFECT-FREE? 170;; 171;; True iff evaluation of expression has no side effects. 172(declare (integrate-operator expression/effect-free?)) 173(define (expression/effect-free? expression) 174 ((expression/method effect-free?-dispatch-vector expression) expression)) 175 176(define effect-free?-dispatch-vector 177 (expression/make-dispatch-vector)) 178 179(define define-method/effect-free? 180 (expression/make-method-definer effect-free?-dispatch-vector)) 181 182(define-method/effect-free? 'ACCESS 183 (lambda (expression) 184 (expression/effect-free? (access/environment expression)))) 185 186(define-method/effect-free? 'ASSIGNMENT false-procedure) 187 188(define-method/effect-free? 'COMBINATION 189 (lambda (expression) 190 (and (for-all? (combination/operands expression) expression/effect-free?) 191 (or (expression/call-to-effect-free-primitive? expression) 192 (and (procedure? (combination/operator expression)) 193 (expression/effect-free? (procedure/body (combination/operator expression)))))))) 194 195(define-method/effect-free? 'CONDITIONAL 196 (lambda (expression) 197 (and (expression/effect-free? (conditional/predicate expression)) 198 (or (expression/always-false? (conditional/predicate expression)) 199 (expression/effect-free? (conditional/consequent expression))) 200 (or (expression/never-false? (conditional/predicate expression)) 201 (expression/effect-free? (conditional/alternative expression)))))) 202 203(define-method/effect-free? 'CONSTANT true-procedure) 204 205(define-method/effect-free? 'DECLARATION 206 (lambda (expression) 207 (expression/effect-free? (declaration/expression expression)))) 208 209;; Consing a promise is not considered an effect. 210(define-method/effect-free? 'DELAY true-procedure) 211 212(define-method/effect-free? 'DISJUNCTION 213 (lambda (expression) 214 (and (expression/effect-free? (disjunction/predicate expression)) 215 (or (expression/never-false? (disjunction/predicate expression)) 216 (expression/effect-free? (disjunction/alternative expression)))))) 217 218;; This could be smarter and skip the assignments 219;; done for the letrec, but it is easier to just 220;; assume it causes effects. 221(define-method/effect-free? 'OPEN-BLOCK 222 (lambda (expression) 223 (declare (ignore expression)) 224 #f)) 225 226;; Just consing a closure is not considered a side-effect. 227(define-method/effect-free? 'PROCEDURE true-procedure) 228 229(define-method/effect-free? 'QUOTATION false-procedure) 230 231(define-method/effect-free? 'REFERENCE true-procedure) 232 233(define-method/effect-free? 'SEQUENCE 234 (lambda (expression) 235 (for-all? (sequence/actions expression) expression/effect-free?))) 236 237(define-method/effect-free? 'THE-ENVIRONMENT true-procedure) 238 239;;; EXPRESSION/FREE-VARIABLES 240;; 241;; Returns an EQ? LSET of the free variables in an expression. 242 243(declare (integrate-operator expression/free-variables)) 244 245(define (expression/free-variables expression) 246 ((expression/method free-variables-dispatch-vector expression) expression)) 247 248(define (expressions/free-variables expressions) 249 (fold-left (lambda (answer expression) 250 (lset-union eq? answer (expression/free-variables expression))) 251 (no-free-variables) 252 expressions)) 253 254(define free-variables-dispatch-vector 255 (expression/make-dispatch-vector)) 256 257(define define-method/free-variables 258 (expression/make-method-definer free-variables-dispatch-vector)) 259 260(define-method/free-variables 'ACCESS 261 (lambda (expression) 262 (expression/free-variables (access/environment expression)))) 263 264(define-method/free-variables 'ASSIGNMENT 265 (lambda (expression) 266 (lset-adjoin eq? 267 (expression/free-variables (assignment/value expression)) 268 (assignment/variable expression)))) 269 270(define-method/free-variables 'COMBINATION 271 (lambda (expression) 272 (lset-union eq? 273 (expression/free-variables (combination/operator expression)) 274 (expressions/free-variables (combination/operands expression))))) 275 276(define-method/free-variables 'CONDITIONAL 277 (lambda (expression) 278 (lset-union eq? 279 (expression/free-variables (conditional/predicate expression)) 280 (if (expression/always-false? (conditional/predicate expression)) 281 (no-free-variables) 282 (expression/free-variables (conditional/consequent expression))) 283 (if (expression/never-false? (conditional/predicate expression)) 284 (no-free-variables) 285 (expression/free-variables (conditional/alternative expression)))))) 286 287(define-method/free-variables 'CONSTANT 288 (lambda (expression) 289 expression 290 (no-free-variables))) 291 292(define-method/free-variables 'DECLARATION 293 (lambda (expression) 294 (expression/free-variables (declaration/expression expression)))) 295 296(define-method/free-variables 'DELAY 297 (lambda (expression) 298 (expression/free-variables (delay/expression expression)))) 299 300(define-method/free-variables 'DISJUNCTION 301 (lambda (expression) 302 (lset-union eq? 303 (expression/free-variables (disjunction/predicate expression)) 304 (if (expression/never-false? (disjunction/predicate expression)) 305 (no-free-variables) 306 (expression/free-variables (disjunction/alternative expression)))))) 307 308(define-method/free-variables 'OPEN-BLOCK 309 (lambda (expression) 310 (let ((omit (block/bound-variables (open-block/block expression)))) 311 (fold-left (lambda (variables action) 312 (if (eq? action open-block/value-marker) 313 variables 314 (lset-union eq? variables (lset-difference eq? (expression/free-variables action) omit)))) 315 (lset-difference eq? (expressions/free-variables (open-block/values expression)) omit) 316 (open-block/actions expression))))) 317 318(define-method/free-variables 'PROCEDURE 319 (lambda (expression) 320 (lset-difference eq? 321 (expression/free-variables (procedure/body expression)) 322 (block/bound-variables (procedure/block expression))))) 323 324(define-method/free-variables 'QUOTATION 325 (lambda (expression) 326 (declare (ignore expression)) 327 (no-free-variables))) 328 329(define-method/free-variables 'REFERENCE 330 (lambda (expression) 331 (singleton-variable (reference/variable expression)))) 332 333(define-method/free-variables 'SEQUENCE 334 (lambda (expression) 335 (expressions/free-variables (sequence/actions expression)))) 336 337(define-method/free-variables 'THE-ENVIRONMENT 338 (lambda (expression) 339 (declare (ignore expression)) 340 (no-free-variables))) 341 342(define-integrable (no-free-variables) 343 '()) 344 345(define-integrable (singleton-variable variable) 346 (list variable)) 347 348;;; EXPRESSION/FREE-VARIABLE? <expression> <variable> 349;; 350;; Test if a particular <variable> occurs free in <expression>. Faster 351;; and cheaper than collecting the entire free variable set and then 352;; using memq. 353 354(define (expression/free-variable? expression variable) 355 ((expression/method is-free-dispatch-vector expression) expression variable)) 356 357(define (expressions/free-variable? expressions variable) 358 (fold-left (lambda (answer expression) 359 (or answer 360 (expression/free-variable? expression variable))) 361 #f 362 expressions)) 363 364(define is-free-dispatch-vector 365 (expression/make-dispatch-vector)) 366 367(define define-method/free-variable? 368 (expression/make-method-definer is-free-dispatch-vector)) 369 370(define-method/free-variable? 'ACCESS 371 (lambda (expression variable) 372 (expression/free-variable? (access/environment expression) variable))) 373 374(define-method/free-variable? 'ASSIGNMENT 375 (lambda (expression variable) 376 (or (eq? variable (assignment/variable expression)) 377 (expression/free-variable? (assignment/value expression) variable)))) 378 379(define-method/free-variable? 'COMBINATION 380 (lambda (expression variable) 381 (or (expression/free-variable? (combination/operator expression) variable) 382 (expressions/free-variable? (combination/operands expression) variable)))) 383 384(define-method/free-variable? 'CONDITIONAL 385 (lambda (expression variable) 386 (or (expression/free-variable? (conditional/predicate expression) variable) 387 (cond ((expression/always-false? (conditional/predicate expression)) 388 (expression/free-variable? (conditional/alternative expression) variable)) 389 ((expression/never-false? (conditional/predicate expression)) 390 (expression/free-variable? (conditional/consequent expression) variable)) 391 ((expression/free-variable? (conditional/consequent expression) variable)) 392 (else (expression/free-variable? (conditional/alternative expression) variable)))))) 393 394(define-method/free-variable? 'CONSTANT false-procedure) 395 396(define-method/free-variable? 'DECLARATION 397 (lambda (expression variable) 398 (expression/free-variable? (declaration/expression expression) variable))) 399 400(define-method/free-variable? 'DELAY 401 (lambda (expression variable) 402 (expression/free-variable? (delay/expression expression) variable))) 403 404(define-method/free-variable? 'DISJUNCTION 405 (lambda (expression variable) 406 (or (expression/free-variable? (disjunction/predicate expression) variable) 407 (if (expression/never-false? (disjunction/predicate expression)) 408 #f 409 (expression/free-variable? (disjunction/alternative expression) variable))))) 410 411(define-method/free-variable? 'OPEN-BLOCK 412 (lambda (expression variable) 413 (fold-left (lambda (answer action) 414 (or answer 415 (if (eq? action open-block/value-marker) 416 #f 417 (expression/free-variable? action variable)))) 418 #f 419 (open-block/actions expression)))) 420 421(define-method/free-variable? 'PROCEDURE 422 (lambda (expression variable) 423 (expression/free-variable? (procedure/body expression) variable))) 424 425(define-method/free-variable? 'QUOTATION false-procedure) 426 427(define-method/free-variable? 'REFERENCE 428 (lambda (expression variable) 429 (eq? (reference/variable expression) variable))) 430 431(define-method/free-variable? 'SEQUENCE 432 (lambda (expression variable) 433 (fold-left (lambda (answer action) 434 (or answer 435 (if (eq? action open-block/value-marker) 436 #f 437 (expression/free-variable? action variable)))) 438 #f 439 (sequence/actions expression)))) 440 441(define-method/free-variable? 'THE-ENVIRONMENT false-procedure) 442 443;;; EXPRESSION/FREE-VARIABLE-INFO <expression> <variable> 444;; 445;; Returns a PAIR, the car of which contains a count of the number 446;; of times the variable appears as an operator, the cdr contains 447;; the number of times the variable appears as an argument. 448;; Used to determine if adding an INTEGRATE-OPERATOR declaration 449;; is a good idea. 450 451(define (expression/free-variable-info expression variable) 452 (expression/free-variable-info-dispatch expression variable (cons 0 0))) 453 454(define (expression/free-variable-info-dispatch expression variable info) 455 ((expression/method free-info-dispatch-vector expression) expression variable info)) 456 457(define (expressions/free-variable-info expressions variable info) 458 (fold-left (lambda (answer expression) 459 (expression/free-variable-info-dispatch expression variable answer)) 460 info 461 expressions)) 462 463(define free-info-dispatch-vector 464 (expression/make-dispatch-vector)) 465 466(define define-method/free-variable-info 467 (expression/make-method-definer free-info-dispatch-vector)) 468 469(define-method/free-variable-info 'ACCESS 470 (lambda (expression variable info) 471 (expression/free-variable-info-dispatch (access/environment expression) variable info))) 472 473(define-method/free-variable-info 'ASSIGNMENT 474 (lambda (expression variable info) 475 (or (eq? variable (assignment/variable expression)) 476 (expression/free-variable-info-dispatch (assignment/value expression) variable info)))) 477 478(define-method/free-variable-info 'COMBINATION 479 (lambda (expression variable info) 480 (let ((operator (combination/operator expression)) 481 (inner-info (expressions/free-variable-info (combination/operands expression) variable info))) 482 (if (and (reference? operator) 483 (eq? (reference/variable operator) variable)) 484 (cons (fix:1+ (car inner-info)) (cdr inner-info)) 485 (expression/free-variable-info-dispatch operator variable inner-info))))) 486 487(define-method/free-variable-info 'CONDITIONAL 488 (lambda (expression variable info) 489 (expression/free-variable-info-dispatch 490 (conditional/predicate expression) variable 491 (expression/free-variable-info-dispatch 492 (conditional/consequent expression) variable 493 (expression/free-variable-info-dispatch (conditional/alternative expression) variable info))))) 494 495(define-method/free-variable-info 'CONSTANT 496 (lambda (expression variable info) (declare (ignore expression variable)) info)) 497 498(define-method/free-variable-info 'DECLARATION 499 (lambda (expression variable info) 500 (expression/free-variable-info-dispatch (declaration/expression expression) variable info))) 501 502(define-method/free-variable-info 'DELAY 503 (lambda (expression variable info) 504 (expression/free-variable-info-dispatch (delay/expression expression) variable info))) 505 506(define-method/free-variable-info 'DISJUNCTION 507 (lambda (expression variable info) 508 (expression/free-variable-info-dispatch 509 (disjunction/predicate expression) variable 510 (expression/free-variable-info-dispatch 511 (disjunction/alternative expression) variable 512 info)))) 513 514(define-method/free-variable-info 'OPEN-BLOCK 515 (lambda (expression variable info) 516 (fold-left (lambda (info action) 517 (if (eq? action open-block/value-marker) 518 info 519 (expression/free-variable-info-dispatch action variable info))) 520 info 521 (open-block/actions expression)))) 522 523(define-method/free-variable-info 'PROCEDURE 524 (lambda (expression variable info) 525 (expression/free-variable-info-dispatch (procedure/body expression) variable info))) 526 527(define-method/free-variable-info 'QUOTATION 528 (lambda (expression variable info) 529 (declare (ignore expression variable)) 530 info)) 531 532(define-method/free-variable-info 'REFERENCE 533 (lambda (expression variable info) 534 (if (eq? (reference/variable expression) variable) 535 (cons (car info) (fix:1+ (cdr info))) 536 info))) 537 538(define-method/free-variable-info 'SEQUENCE 539 (lambda (expression variable info) 540 (expressions/free-variable-info (sequence/actions expression) variable info))) 541 542(define-method/free-variable-info 'THE-ENVIRONMENT 543 (lambda (expression variable info) 544 (declare (ignore expression variable)) 545 info)) 546 547;;; EXPRESSION/NEVER-FALSE? 548;; 549;; True iff expression can be shown to never return #F. 550;; That is, the expression counts as #t to a conditional. 551;; Expression is not shown to be side-effect free. 552(declare (integrate-operator expression/never-false?)) 553(define (expression/never-false? expression) 554 ((expression/method never-false?-dispatch-vector expression) expression)) 555 556(define never-false?-dispatch-vector 557 (expression/make-dispatch-vector)) 558 559(define define-method/never-false? 560 (expression/make-method-definer never-false?-dispatch-vector)) 561 562(define-method/never-false? 'ACCESS false-procedure) 563 564(define-method/never-false? 'ASSIGNMENT false-procedure) 565 566(define-method/never-false? 'COMBINATION 567 (lambda (expression) 568 (cond ((expression/call-to-not? expression) 569 (expression/always-false? (first (combination/operands expression)))) 570 ((procedure? (combination/operator expression)) 571 (expression/never-false? (procedure/body (combination/operator expression)))) 572 (else #f)))) 573 574(define-method/never-false? 'CONDITIONAL 575 (lambda (expression) 576 (and (or (expression/always-false? (conditional/predicate expression)) 577 (expression/never-false? (conditional/consequent expression))) 578 (or (expression/never-false? (conditional/predicate expression)) 579 (expression/never-false? (conditional/alternative expression)))))) 580 581(define-method/never-false? 'CONSTANT constant/value) 582 583(define-method/never-false? 'DECLARATION 584 (lambda (expression) 585 (expression/never-false? (declaration/expression expression)))) 586 587(define-method/never-false? 'DELAY true-procedure) 588 589(define-method/never-false? 'DISJUNCTION 590 (lambda (expression) 591 (or (expression/never-false? (disjunction/predicate expression)) 592 (expression/never-false? (disjunction/alternative expression))))) 593 594(define-method/never-false? 'OPEN-BLOCK 595 (lambda (expression) 596 (expression/never-false? 597 (last (open-block/actions expression))))) 598 599(define-method/never-false? 'PROCEDURE true-procedure) 600 601(define-method/never-false? 'QUOTATION false-procedure) 602 603(define-method/never-false? 'REFERENCE false-procedure) 604 605(define-method/never-false? 'SEQUENCE 606 (lambda (expression) 607 (expression/never-false? (last (sequence/actions expression))))) 608 609(define-method/never-false? 'THE-ENVIRONMENT true-procedure) 610 611;;; EXPRESSION/PURE-FALSE? 612 613;; True iff all paths through expression end in returning 614;; exactly #F or unspecified, and no path has side effects. 615;; Expression is observationally equivalent to #F. 616(define (expression/pure-false? expression) 617 ((expression/method pure-false?-dispatch-vector expression) expression)) 618 619(define pure-false?-dispatch-vector 620 (expression/make-dispatch-vector)) 621 622(define define-method/pure-false? 623 (expression/make-method-definer pure-false?-dispatch-vector)) 624 625(define-method/pure-false? 'ACCESS false-procedure) 626 627(define-method/pure-false? 'ASSIGNMENT false-procedure) 628 629(define-method/pure-false? 'COMBINATION 630 (lambda (expression) 631 (cond ((expression/call-to-not? expression) 632 (expression/pure-true? (first (combination/operands expression)))) 633 ((procedure? (combination/operator expression)) 634 (and (for-all? (combination/operands expression) expression/effect-free?) 635 (expression/pure-false? (procedure/body (combination/operator expression))))) 636 (else #f)))) 637 638(define-method/pure-false? 'CONDITIONAL 639 (lambda (expression) 640 (and (expression/effect-free? (conditional/predicate expression)) 641 (or (expression/always-false? (conditional/predicate expression)) 642 (expression/pure-false? (conditional/consequent expression))) 643 (or (expression/never-false? (conditional/predicate expression)) 644 (expression/pure-false? (conditional/alternative expression)))))) 645 646(define-method/pure-false? 'CONSTANT 647 (lambda (expression) 648 (not (constant/value expression)))) 649 650(define-method/pure-false? 'DECLARATION 651 (lambda (expression) 652 (expression/pure-false? 653 (declaration/expression expression)))) 654 655(define-method/pure-false? 'DELAY false-procedure) 656 657(define-method/pure-false? 'DISJUNCTION 658 (lambda (expression) 659 (and (expression/pure-false? (disjunction/predicate expression)) 660 (expression/pure-false? (disjunction/alternative expression))))) 661 662;; Could be smarter 663(define-method/pure-false? 'OPEN-BLOCK false-procedure) 664 665(define-method/pure-false? 'PROCEDURE false-procedure) 666 667(define-method/pure-false? 'QUOTATION false-procedure) 668 669(define-method/pure-false? 'REFERENCE false-procedure) 670 671(define-method/pure-false? 'SEQUENCE 672 (lambda (expression) 673 (and (for-all? (except-last-pair (sequence/actions expression)) 674 expression/effect-free?) ;; unlikely 675 (expression/pure-false? (last (sequence/actions expression)))))) 676 677(define-method/pure-false? 'THE-ENVIRONMENT false-procedure) 678 679;;; EXPRESSION/PURE-TRUE? 680;; 681;; True iff all paths through expression end in returning 682;; exactly #T or unspecified, and no path has side effects. 683;; Expression is observationally equivalent to #T. 684(declare (integrate-operator expression/pure-true?)) 685(define (expression/pure-true? expression) 686 ((expression/method pure-true?-dispatch-vector expression) expression)) 687 688(define pure-true?-dispatch-vector 689 (expression/make-dispatch-vector)) 690 691(define define-method/pure-true? 692 (expression/make-method-definer pure-true?-dispatch-vector)) 693 694(define-method/pure-true? 'ACCESS false-procedure) 695 696(define-method/pure-true? 'ASSIGNMENT false-procedure) 697 698(define-method/pure-true? 'COMBINATION 699 (lambda (expression) 700 (cond ((expression/call-to-not? expression) 701 (expression/pure-false? (first (combination/operands expression)))) 702 ((procedure? (combination/operator expression)) 703 (and (for-all? (combination/operands expression) expression/effect-free?) 704 (expression/pure-true? (procedure/body (combination/operator expression))))) 705 (else #f)))) 706 707(define-method/pure-true? 'CONDITIONAL 708 (lambda (expression) 709 (and (expression/effect-free? (conditional/predicate expression)) 710 (or (expression/always-false? (conditional/predicate expression)) 711 (expression/pure-true? (conditional/consequent expression))) 712 (or (expression/never-false? (conditional/predicate expression)) 713 (expression/pure-true? (conditional/alternative expression)))))) 714 715(define-method/pure-true? 'CONSTANT 716 (lambda (expression) 717 (eq? (constant/value expression) #t))) 718 719(define-method/pure-true? 'DECLARATION 720 (lambda (expression) 721 (expression/pure-true? (declaration/expression expression)))) 722 723(define-method/pure-true? 'DELAY false-procedure) 724 725(define-method/pure-true? 'DISJUNCTION 726 (lambda (expression) 727 (and (expression/effect-free? (disjunction/predicate expression)) 728 (expression/boolean? (disjunction/predicate expression)) 729 (expression/pure-true? (disjunction/alternative expression))))) 730 731(define-method/pure-true? 'OPEN-BLOCK false-procedure) 732 733(define-method/pure-true? 'PROCEDURE false-procedure) 734 735(define-method/pure-true? 'QUOTATION false-procedure) 736 737(define-method/pure-true? 'REFERENCE false-procedure) 738 739(define-method/pure-true? 'SEQUENCE 740 (lambda (expression) 741 (and (for-all? (except-last-pair (sequence/actions expression)) 742 expression/effect-free?) 743 (expression/pure-true? (last (sequence/actions expression)))))) 744 745(define-method/pure-true? 'THE-ENVIRONMENT false-procedure) 746 747;;; EXPRESSION/SIZE <expr> 748;; 749;; Returns an integer count of the number of SCode nodes in the expression. 750;; Used to avoid exponential code bloat when adding INTEGRATE-OPERATOR 751;; declarations. 752(declare (integrate-operator expression/size)) 753 754(define (expression/size expression) 755 ((expression/method size-dispatch-vector expression) expression)) 756 757(define size-dispatch-vector 758 (expression/make-dispatch-vector)) 759 760(define define-method/size 761 (expression/make-method-definer size-dispatch-vector)) 762 763(define-method/size 'ACCESS 764 (lambda (expression) 765 (fix:1+ (expression/size (access/environment expression))))) 766 767(define-method/size 'ASSIGNMENT 768 (lambda (expression) 769 (fix:1+ (expression/size (assignment/value expression))))) 770 771(define-method/size 'COMBINATION 772 (lambda (expression) 773 (fold-left (lambda (total operand) 774 (fix:+ total (expression/size operand))) 775 (fix:1+ (expression/size (combination/operator expression))) 776 (combination/operands expression)))) 777 778(define-method/size 'CONDITIONAL 779 (lambda (expression) 780 (fix:+ 781 (expression/size (conditional/predicate expression)) 782 (fix:+ 783 (expression/size (conditional/consequent expression)) 784 (fix:1+ (expression/size (conditional/alternative expression))))))) 785 786(define-method/size 'CONSTANT 787 (lambda (expression) (declare (ignore expression)) 1)) 788 789(define-method/size 'DECLARATION 790 (lambda (expression) 791 (fix:1+ (expression/size (declaration/expression expression))))) 792 793(define-method/size 'DELAY 794 (lambda (expression) 795 (fix:1+ (expression/size (delay/expression expression))))) 796 797(define-method/size 'DISJUNCTION 798 (lambda (expression) 799 (fix:+ (expression/size (disjunction/predicate expression)) 800 (fix:1+ (expression/size (disjunction/alternative expression)))))) 801 802(define-method/size 'OPEN-BLOCK 803 (lambda (expression) 804 (fold-left (lambda (total action) 805 (if (eq? action open-block/value-marker) 806 total 807 (fix:+ total (expression/size action)))) 808 1 809 (open-block/actions expression)))) 810 811(define-method/size 'PROCEDURE 812 (lambda (expression) 813 (fix:1+ (expression/size (procedure/body expression))))) 814 815(define-method/size 'QUOTATION 816 (lambda (expression) 817 (fix:1+ (expression/size (quotation/expression expression))))) 818 819(define-method/size 'REFERENCE 820 (lambda (expression) 821 (declare (ignore expression)) 822 1)) 823 824(define-method/size 'SEQUENCE 825 (lambda (expression) 826 (fold-left (lambda (total action) 827 (fix:+ total (expression/size action))) 828 1 829 (sequence/actions expression)))) 830 831;;; EXPRESSION->list <expr> 832;; 833;; Returns an list representation of the SCode nodes in the expression. 834;; Used for debugging sf. 835 836(define (expression->list expression) 837 ((expression/method expression->list-dispatch-vector expression) expression)) 838 839(define expression->list-dispatch-vector 840 (expression/make-dispatch-vector)) 841 842(define define-method/expression->list 843 (expression/make-method-definer expression->list-dispatch-vector)) 844 845(define-method/expression->list 'ACCESS 846 (lambda (expression) 847 `(ACCESS ,(access/name expression) 848 ,(expression->list (access/environment expression))))) 849 850(define-method/expression->list 'ASSIGNMENT 851 (lambda (expression) 852 `(SET! ,(assignment/variable expression) 853 ,(expression->list (assignment/value expression))))) 854 855(define-method/expression->list 'COMBINATION 856 (lambda (expression) 857 (cons (expression->list (combination/operator expression)) 858 (map expression->list (combination/operands expression))))) 859 860(define-method/expression->list 'CONDITIONAL 861 (lambda (expression) 862 `(IF ,(expression->list (conditional/predicate expression)) 863 ,(expression->list (conditional/consequent expression)) 864 ,(expression->list (conditional/alternative expression))))) 865 866(define-method/expression->list 'CONSTANT 867 (lambda (expression) (constant/value expression))) 868 869(define-method/expression->list 'DECLARATION 870 (lambda (expression) 871 `(DECLARE ,(declaration/declarations expression) 872 ,(expression->list (declaration/expression expression))))) 873 874(define-method/expression->list 'DELAY 875 (lambda (expression) 876 `(DELAY ,(expression->list (delay/expression expression))))) 877 878(define-method/expression->list 'DISJUNCTION 879 (lambda (expression) 880 `(OR ,(expression->list (disjunction/predicate expression)) 881 ,(expression->list (disjunction/alternative expression))))) 882 883(define-method/expression->list 'OPEN-BLOCK 884 (lambda (expression) 885 `(OPEN-BLOCK 886 ',(map variable/name (open-block/variables expression)) 887 ,@(map (lambda (action) 888 (if (eq? action open-block/value-marker) 889 `(QUOTE ,action) 890 (expression->list action))) 891 (open-block/actions expression))))) 892 893(define-method/expression->list 'PROCEDURE 894 (lambda (expression) 895 (let ((name (procedure/name expression)) 896 (required (map variable/name (procedure/required expression))) 897 (optional (map variable/name (procedure/optional expression))) 898 (rest (let ((rest-arg (procedure/rest expression))) 899 (and rest-arg 900 (variable/name rest-arg))))) 901 `(PROCEDURE ,name 902 ,(make-lambda-list required optional rest '()) 903 ,(expression->list (procedure/body expression)))))) 904 905(define-method/expression->list 'QUOTATION 906 (lambda (expression) 907 `(QUOTE ,(quotation/expression expression)))) 908 909(define-method/expression->list 'REFERENCE 910 (lambda (expression) 911 (variable/name (reference/variable expression)))) 912 913(define-method/expression->list 'SEQUENCE 914 (lambda (expression) 915 `(BEGIN ,@(map expression->list (sequence/actions expression))))) 916