cyclone/scheme/cyclone/cps-opt-local-var-redux.scm
2018-12-20 13:25:52 -05:00

437 lines
17 KiB
Scheme

;;;; Cyclone Scheme
;;;; https://github.com/justinethier/cyclone
;;;;
;;;; Copyright (c) 2014-2018, Justin Ethier
;;;; All rights reserved.
;;;;
;;;; This file is part of the cps-optimizations module.
;;;;
(cond-expand
(program
(import (scheme base)
(scheme write)
(scheme cyclone ast)
(scheme cyclone primitives)
(scheme cyclone util)
(scheme cyclone pretty-print))))
;; Local variable reduction:
;; Reduce given sexp by replacing certain lambda calls with a let containing
;; local variables. Based on the way cyclone transforms code, this will
;; typically be limited to if expressions embedded in other expressions.
(define (opt:local-var-reduction sexp)
(define (scan exp)
;(write `(DEBUG scan ,exp)) (newline)
(cond
((ast:lambda? exp)
(ast:%make-lambda
(ast:lambda-id exp)
(ast:lambda-args exp)
(map scan (ast:lambda-body exp))
(ast:lambda-has-cont exp)))
((quote? exp) exp)
((const? exp) exp)
((ref? exp) exp)
((define? exp)
`(define
,(define->var exp)
,@(map scan (define->exp exp))))
((set!? exp)
`(set!
,(scan (set!->var exp))
,(scan (set!->exp exp))))
((if? exp)
`(if ,(scan (if->condition exp))
,(scan (if->then exp))
,(scan (if->else exp))))
((app? exp)
(cond
((and
(list? exp)
(ast:lambda? (car exp))
(equal? (length exp) 2)
(ast:lambda? (cadr exp))
(list? (ast:lambda-args (cadr exp)))
(equal? 1 (length (ast:lambda-args (cadr exp))))
(lvr:local-tail-call-only?
(ast:lambda-body (car exp))
(car (ast:lambda-args (car exp))))
;(tagged-list? 'Cyc-seq (car (ast:lambda-body (cadr exp)))) ;; TODO: DEBUG line, remove this once it works!
)
;;(write `(tail-call-only? passed for ,exp)) (newline)
;;(write `(replace with ,(lvr:tail-calls->values
;; (car (ast:lambda-body (car exp)))
;; (car (ast:lambda-args (car exp))))))
;;(newline)
;TODO: need to revisit this, may need to replace values with assignments to the "let" variable.
;would need to be able to carry that through to cgen and assign properly over there...
(let* ((value (lvr:tail-calls->values
(car (ast:lambda-body (car exp)))
(car (ast:lambda-args (car exp)))
(car (ast:lambda-args (cadr exp)))
))
(var (car (ast:lambda-args (cadr exp))))
(body (ast:lambda-body (cadr exp)))
(av (cond-expand
(program #f)
(else (adb:get/default var #f))))
(ref-count
(if av
(cond-expand
(program #f)
(else (adbv:ref-count av)))
1)) ;; Dummy value
)
(if (and (> ref-count 0) ;; 0 ==> local var is never used
value)
`(let ((,var ,value))
,@body)
(map scan exp)) ;; failsafe
))
(else
(map scan exp))))
(else (error "unknown expression type: " exp))
))
(scan sexp))
;; Local variable reduction helper:
;; Scan sexp to determine if sym is only called in a tail-call position
(define (lvr:local-tail-call-only? sexp sym)
(call/cc
(lambda (return)
(define (scan exp fail?)
;;(write `(DEBUG lvr:local-tail-call-only? scan ,exp)) (newline)
(cond
((ast:lambda? exp)
(return #f)) ;; Could be OK if not ref'd...
((quote? exp) exp)
((const? exp) exp)
((ref? exp)
(if (equal? exp sym)
(return #f))) ;; Assume not a tail call
((define? exp)
(return #f)) ;; Fail fast
((set!? exp)
(return #f)) ;; Fail fast
((if? exp)
(scan (if->condition exp) #t) ;; fail if found under here
(scan (if->then exp) fail?)
(scan (if->else exp) fail?))
((app? exp)
(cond
;;; TODO: may need to check for prim:cont? and abort accordingly
;; check out code generated for scheme/cyclone/util.sld WRT symbol->string
;; cannot proceed with this since by definition these functions require CPS
((and (prim? (car exp))
(prim:cont? (car exp)))
(return #f))
((and (equal? (car exp) sym)
(not fail?))
(map (lambda (e) (scan e fail?)) (cdr exp))) ;; Sym is OK, skip
(else
(map (lambda (e) (scan e fail?)) exp))))
(else exp)))
(scan sexp #f)
(return #t))))
;; Local variable reduction helper:
;; Transform all tail calls of sym in the sexp to just the value passed
(define (lvr:tail-calls->values sexp sym assign-sym)
(call/cc
(lambda (return)
(define (scan exp)
;;(write `(DEBUG scan ,exp)) (newline)
(cond
((ast:lambda? exp)
(return #f)) ;; Could be OK if not ref'd...
((quote? exp) exp)
((const? exp) exp)
((ref? exp)
(if (equal? exp sym)
(return #f))) ;; Assume not a tail call
((define? exp)
(return #f)) ;; Fail fast
((set!? exp)
(return #f)) ;; Fail fast
((if? exp)
`(if ,(if->condition exp)
,(scan (if->then exp))
,(scan (if->else exp))))
((app? exp)
(cond
((and (equal? (car exp) sym)
(= (length exp) 2)
)
`(Cyc-local-set! ,assign-sym ,(cadr exp)))
(else
;; TODO: can we be smarter? Consider example from match.scm match-gen-or-step
(return #f))))
(else exp)))
(cond
;((or (quote? sexp)
; (const? sexp))
; ;; Special case, set the value directly
; ;; TODO: this is a bit of a hack, may way to re-think how this
; ;; whole module works at some point, but for now this works.
; (return
; `(Cyc-local-set! ,assign-sym ,sexp)))
(else
(return
(scan sexp)))))))
(cond-expand
(program
(define sexp
'(
;(define zunda
; ((lambda
; (k$1057 first-row-perm$61$668 mat$62$669)
; (first-row-perm$61$668
; (lambda
; (first-row$65$670)
; ((lambda
; (number-of-cols$68$671)
; ((lambda
; (make-row->func$71$672)
; (first-row-perm$61$668
; (lambda
; (r$1062)
; (make-row->func$71$672
; (lambda
; (r$1063)
; (make-row->func$71$672
; (lambda
; (r$1064)
; (zebra k$1057
; r$1062
; r$1063
; r$1064
; (cdr mat$62$669)
; number-of-cols$68$671))
; -1
; 1))
; 1
; -1))
; 'child))
; (lambda
; (k$1066 if-equal$76$674 if-different$77$675)
; (k$1066
; (lambda
; (k$1067 row$78$676)
; ((lambda
; (vec$79$677)
; ((lambda
; (first$85$679 row$86$680)
; ((lambda
; (lp$80$87$681)
; ((lambda
; (lp$80$87$681)
; (Cyc-seq
; (set!
; lp$80$87$681
; (lambda
; (k$1073 i$88$682 first$89$683 row$90$684)
; (if (Cyc-fast-eq
; i$88$682
; number-of-cols$68$671)
; (k$1073
; (Cyc-fast-eq
; i$88$682
; number-of-cols$68$671))
; ((lambda
; (k$1080)
; (if (Cyc-fast-eq
; (car first$89$683)
; (car row$90$684))
; (k$1080 if-equal$76$674)
; (k$1080 if-different$77$675)))
; (lambda
; (r$1079)
; (Cyc-seq
; (vector-set!
; vec$79$677
; i$88$682
; r$1079)
; ((cell-get lp$80$87$681)
; k$1073
; (Cyc-fast-plus i$88$682 1)
; (cdr first$89$683)
; (cdr row$90$684))))))))
; ((cell-get lp$80$87$681)
; (lambda
; (r$1069)
; (k$1067
; (lambda
; (k$1070 i$92$686)
; (k$1070
; (vector-ref vec$79$677 i$92$686)))))
; 0
; first$85$679
; row$86$680)))
; (cell lp$80$87$681)))
; #f))
; first-row$65$670
; row$78$676))
; (make-vector number-of-cols$68$671)))))))
; (length first-row$65$670)))
; 'now))))
; (define *num-passed* 0)
;(define write-to-string
; (lambda
; (k$3086 x$892$1775)
; (call-with-output-string
; k$3086
; (lambda
; (k$3088 out$893$1776)
; ((lambda
; (x$895$1777)
; ((lambda
; (wr$896$1778)
; (Cyc-seq
; (set! wr$896$1778
; (lambda
; (k$3091 x$897$1779)
; (if (pair? x$897$1779)
; ((lambda
; (k$3112)
; (if (symbol? (car x$897$1779))
; (if (pair? (cdr x$897$1779))
; (if (null? (cddr x$897$1779))
; (k$3112
; (assq (car x$897$1779)
; '((quote . "'")
; (quasiquote . "`")
; (unquote . ",")
; (unquote-splicing . ",@"))))
; (k$3112 #f))
; (k$3112 #f))
; (k$3112 #f)))
; (lambda
; (tmp$900$902$1780)
; (if tmp$900$902$1780
; ((lambda
; (s$903$1781)
; (display
; (lambda
; (r$3094)
; (wr$896$1778 k$3091 (cadr x$897$1779)))
; (cdr s$903$1781)
; out$893$1776))
; tmp$900$902$1780)
; (display
; (lambda
; (r$3097)
; (wr$896$1778
; (lambda
; (r$3098)
; ((lambda
; (lp$907$1783)
; (Cyc-seq
; (set! lp$907$1783
; (lambda
; (k$3103 ls$908$1784)
; (if (pair? ls$908$1784)
; (display
; (lambda
; (r$3105)
; (wr$896$1778
; (lambda
; (r$3106)
; (lp$907$1783
; k$3103
; (cdr ls$908$1784)))
; (car ls$908$1784)))
; " "
; out$893$1776)
; (if (null? ls$908$1784)
; (k$3103 #f)
; (display
; (lambda
; (r$3110)
; (write k$3103
; ls$908$1784
; out$893$1776))
; " . "
; out$893$1776)))))
; (lp$907$1783
; (lambda
; (r$3099)
; (display k$3091 ")" out$893$1776))
; (cdr x$897$1779))))
; #f))
; (car x$897$1779)))
; "("
; out$893$1776))))
; (write k$3091 x$897$1779 out$893$1776))))
; (wr$896$1778 k$3088 x$895$1777)))
; #f))
; x$892$1775)))))
;(define match-gen-or-step
; (lambda
; (k$14021
; expr$3499$3540$3621$9398
; rename$3500$3541$3622$9399
; compare$3501$3542$3623$9400)
; ((lambda
; (v.1$3507$3599$3659$9436)
; ((lambda
; (k$14141)
; (if (pair? v.1$3507$3599$3659$9436)
; (Cyc-seq
; (car v.1$3507$3599$3659$9436)
; (if (pair? (cdr v.1$3507$3599$3659$9436))
; (if (null? (car (cdr v.1$3507$3599$3659$9436)))
; (if (pair? (cdr (cdr v.1$3507$3599$3659$9436)))
; (Cyc-seq
; (car (cdr (cdr v.1$3507$3599$3659$9436)))
; (if (pair? (cdr (cdr (cdr v.1$3507$3599$3659$9436))))
; (Cyc-seq
; (car (cdr (cdr (cdr v.1$3507$3599$3659$9436))))
; (if (pair? (cdr (cdr (cdr (cdr v.1$3507$3599$3659$9436)))))
; (Cyc-seq
; (cdr (cdr (cdr (cdr (cdr v.1$3507$3599$3659$9436)))))
; (k$14141
; (cons (car (cdr (cdr (cdr (cdr v.1$3507$3599$3659$9436)))))
; #f)))
; (k$14141 #f)))
; (k$14141 #f)))
; (k$14141 #f))
; (k$14141 #f))
; (k$14141 #f)))
; (k$14141 #f)))
; (lambda
; (tmp$3544$3546$3624$9401)
; (list
; (lambda (r$14022) (k$14021 (car r$14022)))))))
; (cdr expr$3499$3540$3621$9398))))
(define slot-set!
(lambda
(k$7170
name$2424$3603
obj$2425$3604
idx$2426$3605
val$2427$3606)
((lambda
(vec$2428$3607)
((lambda
(r$7171)
(k$7170
(vector-set! r$7171 idx$2426$3605 val$2427$3606)))
(vector-ref vec$2428$3607 2)))
obj$2425$3604)))
)
)
;(pretty-print
; (ast:ast->pp-sexp
; (ast:sexp->ast sexp)))
(pretty-print
(ast:ast->pp-sexp
(opt:local-var-reduction (ast:sexp->ast sexp)))
)
))