mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-21 06:39:16 +02:00
Issue #248 - Ensure unique lambda ID's/args
During a beta expansion, renumber lambda ID's and rename lambda args if necessary so that we do not introduce duplicates. Dupes are a problem as they throw of the analysis DB and can lead to the optimizer inserting the wrong values when code is optimized-out.
This commit is contained in:
parent
282fb0793c
commit
ebc68e6746
1 changed files with 38 additions and 16 deletions
|
@ -683,7 +683,7 @@
|
||||||
((app? exp)
|
((app? exp)
|
||||||
;; Beta expansion of functions only called once, from CWC
|
;; Beta expansion of functions only called once, from CWC
|
||||||
(if (beta-expand/called-once? exp)
|
(if (beta-expand/called-once? exp)
|
||||||
(set! exp (beta-expand-app exp)))
|
(set! exp (beta-expand-app exp #f)))
|
||||||
;; END
|
;; END
|
||||||
|
|
||||||
(let* ((fnc (opt:contract (car exp))))
|
(let* ((fnc (opt:contract (car exp))))
|
||||||
|
@ -1337,7 +1337,7 @@
|
||||||
(return #f))))
|
(return #f))))
|
||||||
|
|
||||||
;; Check app and beta expand if possible, else just return given code
|
;; Check app and beta expand if possible, else just return given code
|
||||||
(define (beta-expand-app exp)
|
(define (beta-expand-app exp rename-lambdas)
|
||||||
(let* ((args (cdr exp))
|
(let* ((args (cdr exp))
|
||||||
(var (adb:get/default (car exp) #f))
|
(var (adb:get/default (car exp) #f))
|
||||||
;; Function definition, or #f if none
|
;; Function definition, or #f if none
|
||||||
|
@ -1366,34 +1366,56 @@
|
||||||
(list? formals)
|
(list? formals)
|
||||||
(= (length args) (length formals)))
|
(= (length args) (length formals)))
|
||||||
;(trace:error `(JAE DEBUG beta expand ,exp))
|
;(trace:error `(JAE DEBUG beta expand ,exp))
|
||||||
(beta-expansion-app exp fnc) ; exp
|
(beta-expansion-app exp fnc rename-lambdas) ; exp
|
||||||
)
|
)
|
||||||
(else exp)))) ;; beta expansion failed
|
(else exp)))) ;; beta expansion failed
|
||||||
|
|
||||||
;; Replace function call with body of fnc
|
;; Replace function call with body of fnc
|
||||||
(define (beta-expansion-app exp fnc)
|
(define (beta-expansion-app exp fnc rename-lambdas)
|
||||||
;; Mapping from a formal => actual arg
|
;; Mapping from a formal => actual arg
|
||||||
(define formals/actuals
|
(define formals/actuals
|
||||||
(map cons (ast:lambda-args fnc) (cdr exp)))
|
(map cons (ast:lambda-args fnc) (cdr exp)))
|
||||||
(define (replace ref)
|
(define (replace ref renamed)
|
||||||
(let ((r (assoc ref formals/actuals)))
|
(let ((r (assoc ref formals/actuals)))
|
||||||
(if r (cdr r) ref)))
|
(if r
|
||||||
(define (scan exp)
|
(scan (cdr r) renamed)
|
||||||
|
;ref
|
||||||
|
(let ((rn (assoc ref renamed)))
|
||||||
|
(if rn
|
||||||
|
(cdr rn)
|
||||||
|
ref)))))
|
||||||
|
(define (scan exp renamed)
|
||||||
(cond
|
(cond
|
||||||
((ast:lambda? exp)
|
((ast:lambda? exp)
|
||||||
(ast:%make-lambda
|
(if rename-lambdas
|
||||||
(ast:lambda-id exp)
|
(let* ((args (ast:lambda-formals->list exp))
|
||||||
(ast:lambda-args exp)
|
(ltype (ast:lambda-formals-type exp))
|
||||||
(scan (ast:lambda-body exp))
|
(a-lookup (map (lambda (a) (cons a (gensym a))) args)))
|
||||||
(ast:lambda-has-cont exp)))
|
(ast:%make-lambda
|
||||||
|
;; if rename-lambdas also need to rename lambda formals here and
|
||||||
|
;; setup and a-lookup to replace any refs with the renamed formal. the
|
||||||
|
;; problem is, if we don't do this, there will be multiple lambda's with
|
||||||
|
;; the same arg, which causes problems when the optimizer tries to replace
|
||||||
|
;; one with its value, since different instances will have different values
|
||||||
|
(ast:get-next-lambda-id!)
|
||||||
|
(list->lambda-formals
|
||||||
|
(map (lambda (p) (cdr p)) a-lookup)
|
||||||
|
ltype)
|
||||||
|
(scan (ast:lambda-body exp) (append a-lookup renamed))
|
||||||
|
(ast:lambda-has-cont exp)))
|
||||||
|
(ast:%make-lambda
|
||||||
|
(ast:lambda-id exp)
|
||||||
|
(ast:lambda-args exp)
|
||||||
|
(scan (ast:lambda-body exp) renamed)
|
||||||
|
(ast:lambda-has-cont exp))))
|
||||||
((ref? exp)
|
((ref? exp)
|
||||||
(replace exp))
|
(replace exp renamed))
|
||||||
((quote? exp)
|
((quote? exp)
|
||||||
exp)
|
exp)
|
||||||
((app? exp)
|
((app? exp)
|
||||||
(map scan exp))
|
(map (lambda (e) (scan e renamed)) exp))
|
||||||
(else exp)))
|
(else exp)))
|
||||||
(scan (car (ast:lambda-body fnc))))
|
(scan (car (ast:lambda-body fnc)) '()))
|
||||||
|
|
||||||
;; Full beta expansion phase, make a pass over all of the program's AST
|
;; Full beta expansion phase, make a pass over all of the program's AST
|
||||||
(define (opt:beta-expand exp)
|
(define (opt:beta-expand exp)
|
||||||
|
@ -1420,7 +1442,7 @@
|
||||||
,(opt:beta-expand (if->else exp))))
|
,(opt:beta-expand (if->else exp))))
|
||||||
((app? exp)
|
((app? exp)
|
||||||
(let ((code (if (beta-expand? exp)
|
(let ((code (if (beta-expand? exp)
|
||||||
(beta-expand-app exp)
|
(beta-expand-app exp #t)
|
||||||
exp)))
|
exp)))
|
||||||
(map opt:beta-expand code)))
|
(map opt:beta-expand code)))
|
||||||
(else exp)))
|
(else exp)))
|
||||||
|
|
Loading…
Add table
Reference in a new issue