mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-13 07:47:39 +02:00
Added lambda side effect analysis
This commit is contained in:
parent
6881285e0c
commit
1a973cafd8
1 changed files with 30 additions and 3 deletions
|
@ -298,7 +298,7 @@
|
||||||
|
|
||||||
;; Mark each lambda that has side effects.
|
;; Mark each lambda that has side effects.
|
||||||
;; For nested lambdas, if a child has side effects also mark the parent
|
;; For nested lambdas, if a child has side effects also mark the parent
|
||||||
#;(define (analyze-lambda-side-effects exp lid)
|
(define (analyze-lambda-side-effects exp lid)
|
||||||
(cond
|
(cond
|
||||||
((ast:lambda? exp)
|
((ast:lambda? exp)
|
||||||
(let* ((id (ast:lambda-id exp))
|
(let* ((id (ast:lambda-id exp))
|
||||||
|
@ -307,23 +307,48 @@
|
||||||
(for-each
|
(for-each
|
||||||
(lambda (expr)
|
(lambda (expr)
|
||||||
(analyze-lambda-side-effects expr id))
|
(analyze-lambda-side-effects expr id))
|
||||||
(ast:lambda-body exp))))
|
(ast:lambda-body exp))
|
||||||
|
;; If id has side effects, mark parent lid, too
|
||||||
|
(if (and (> lid -1)
|
||||||
|
(adbf:side-effects fnc))
|
||||||
|
(with-fnc! lid (lambda (f)
|
||||||
|
(adbf:set-side-effects! f #t))))))
|
||||||
((const? exp) #f)
|
((const? exp) #f)
|
||||||
((quote? exp) #f)
|
((quote? exp) #f)
|
||||||
((ref? exp) #f)
|
((ref? exp) #f)
|
||||||
((define? exp)
|
((define? exp)
|
||||||
(analyze-lambda-side-effects (define->exp exp) lid))
|
(analyze-lambda-side-effects (define->exp exp) lid))
|
||||||
((set!? exp)
|
((set!? exp)
|
||||||
|
(with-fnc! lid (lambda (fnc)
|
||||||
|
(adbf:set-side-effects! fnc #t)))
|
||||||
(analyze-lambda-side-effects (set!->exp exp) lid))
|
(analyze-lambda-side-effects (set!->exp exp) lid))
|
||||||
((if? exp)
|
((if? exp)
|
||||||
(analyze-lambda-side-effects (if->condition exp) lid)
|
(analyze-lambda-side-effects (if->condition exp) lid)
|
||||||
(analyze-lambda-side-effects (if->then exp) lid)
|
(analyze-lambda-side-effects (if->then exp) lid)
|
||||||
(analyze-lambda-side-effects (if->else exp) lid))
|
(analyze-lambda-side-effects (if->else exp) lid))
|
||||||
((app? exp)
|
((app? exp)
|
||||||
|
(let ((pure-ref #t))
|
||||||
|
;; Check if ref is pure. Note this may give wrong results
|
||||||
|
;; if ref's lambda has not been scanned yet. One solution is
|
||||||
|
;; to make 2 top-level passes of analyze-lambda-side-effects.
|
||||||
|
(if (ref? (car exp))
|
||||||
|
(with-var (car exp) (lambda (var)
|
||||||
|
(if (adbv:defines-lambda-id var)
|
||||||
|
(with-fnc! (adbv:defines-lambda-id var) (lambda (fnc)
|
||||||
|
(if (adbf:side-effects fnc)
|
||||||
|
(set! pure-ref #f))))))))
|
||||||
|
|
||||||
|
;; This lambda has side effects if it calls a mutating prim or
|
||||||
|
;; a function not explicitly marked as having no side effects.
|
||||||
|
(if (or (prim:mutates? (car exp))
|
||||||
|
(and (ref? (car exp))
|
||||||
|
(not pure-ref)))
|
||||||
|
(with-fnc! lid (lambda (fnc)
|
||||||
|
(adbf:set-side-effects! fnc #t))))
|
||||||
(for-each
|
(for-each
|
||||||
(lambda (e)
|
(lambda (e)
|
||||||
(analyze-lambda-side-effects e lid))
|
(analyze-lambda-side-effects e lid))
|
||||||
exp))
|
exp)))
|
||||||
(else
|
(else
|
||||||
#f)))
|
#f)))
|
||||||
|
|
||||||
|
@ -1085,6 +1110,8 @@
|
||||||
|
|
||||||
(define (analyze-cps exp)
|
(define (analyze-cps exp)
|
||||||
(analyze-find-lambdas exp -1)
|
(analyze-find-lambdas exp -1)
|
||||||
|
(analyze-lambda-side-effects exp -1)
|
||||||
|
(analyze-lambda-side-effects exp -1) ;; 2nd pass guarantees lambda purity
|
||||||
(analyze exp -1) ;; Top-level is lambda ID -1
|
(analyze exp -1) ;; Top-level is lambda ID -1
|
||||||
(analyze2 exp) ;; Second pass
|
(analyze2 exp) ;; Second pass
|
||||||
(analyze:find-inlinable-vars exp '()) ;; Identify variables safe to inline
|
(analyze:find-inlinable-vars exp '()) ;; Identify variables safe to inline
|
||||||
|
|
Loading…
Add table
Reference in a new issue