Do not memoize a func with any free variables

This prevents issues where free variables are mutated, causing a function to no longer be pure.
This commit is contained in:
Justin Ethier 2019-02-07 17:57:49 -05:00
parent a843e06f9a
commit a0a9242d64

View file

@ -25,7 +25,7 @@
;; TODO: function to actually scan a def to see if that def can be memoized ;; TODO: function to actually scan a def to see if that def can be memoized
(define (memoizable? var body) (define (memoizable? var body)
(define cont #f) (define cont #f)
(define (scan exp return) (define (scan exp return locals)
;(trace:error `(DEBUG scan ,(ast:ast->pp-sexp exp))) ;(trace:error `(DEBUG scan ,(ast:ast->pp-sexp exp)))
(write `(DEBUG scan ,var ,cont ,(ast:ast->pp-sexp exp))) (newline) (write `(DEBUG scan ,var ,cont ,(ast:ast->pp-sexp exp))) (newline)
(cond (cond
@ -33,27 +33,29 @@
((ast:lambda? exp) ((ast:lambda? exp)
(map (map
(lambda (e) (lambda (e)
(scan e return)) (scan e return (append locals (ast:lambda-formals->list exp))))
(ast:lambda-body exp)) (ast:lambda-body exp))
) )
((quote? exp) exp) ((quote? exp) exp)
((const? exp) #t) ((const? exp) #t)
((ref? exp) ((ref? exp)
TODO: if exp is a global (IE: free var), return false ;; Reject if we have any free variables, in case those are mutated
(when (not (member exp locals))
(return #f))
exp) exp)
((define? exp) ((define? exp)
(return #f)) (return #f))
((set!? exp) ((set!? exp)
(return #f)) (return #f))
((if? exp) ((if? exp)
(scan (if->condition exp) return) (scan (if->condition exp) return locals)
(scan (if->then exp) return) (scan (if->then exp) return locals)
(scan (if->else exp) return)) (scan (if->else exp) return locals))
((app? exp) ((app? exp)
(cond (cond
;(write `( ,(car exp) ,var ,cont)) (newline) ;(write `( ,(car exp) ,var ,cont)) (newline)
((ast:lambda? (car exp)) ((ast:lambda? (car exp))
(scan (car exp) return)) (scan (car exp) return locals))
((or ((or
(equal? (car exp) var) ;; Recursive call to self (equal? (car exp) var) ;; Recursive call to self
(equal? (car exp) cont) ;; Continuation of fnc (equal? (car exp) cont) ;; Continuation of fnc
@ -86,7 +88,7 @@
(return #f))) (return #f)))
(for-each (for-each
(lambda (e) (lambda (e)
(scan e return)) (scan e return locals))
(cdr exp))) (cdr exp)))
(else exp) (else exp)
)) ))
@ -103,7 +105,7 @@
(call/cc (call/cc
(lambda (return) (lambda (return)
(set! cont (car (ast:lambda-args body))) (set! cont (car (ast:lambda-args body)))
(scan body return) (scan body return (cons var (ast:lambda-formals->list body)))
(return #t)))) (return #t))))
(else #f)) (else #f))
) )