Skip to content

Commit

Permalink
Evaluate (setq x 1 y 2...)
Browse files Browse the repository at this point in the history
  • Loading branch information
Wilfred committed Jul 14, 2017
1 parent 7da3c48 commit 410b5e3
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 20 deletions.
38 changes: 25 additions & 13 deletions peval.el
Original file line number Diff line number Diff line change
Expand Up @@ -451,27 +451,39 @@ FORM must be a cons cell."
(`(quote ,sym)
(make-peval-result
:evaluated-p t :value sym))

;; (`(set ,sym ,val)
;; (setq sym (peval--simplify-1 sym bindings))
;; (setq val (peval--simplify-1 val bindings))
;; (if (and (peval-result-evaluated-p)))
;; )

;; TODO: (setq x _ y _)
;; TODO: consider aliasing of mutable values (e.g. two variables
;; pointing to the same list).
(`(setq ,sym ,val)
(setq val (peval--simplify-1 val bindings))
(if (peval-result-evaluated-p val)
(progn
(peval--set-var sym (peval-result-value val) bindings)
(`(setq . ,syms-and-vals)
(setq syms-and-vals (-partition 2 syms-and-vals))
(let ((results
(-map (-lambda ((sym val))
(setq val (peval--simplify-1 val bindings))
(if (peval-result-evaluated-p val)
(peval--set-var sym (peval-result-value val) bindings)
(peval--set-var-unknown sym bindings))
val)
syms-and-vals)))
(if (-all-p #'peval-result-evaluated-p results)
(-last-item results)
(let ((syms (-map #'-first-item syms-and-vals)))
;; TODO: (setq x 1 y (unknown)) => (setq y unknown)
;; if x is unused elsewhere.
(make-peval-result
:evaluated-p t
:value (peval-result-value val)))
(peval--set-var-unknown sym bindings)
(make-peval-result
:evaluated-p nil
:value `(setq ,sym ,(peval-result-value val)))))
:evaluated-p nil :value
;; TODO: Use splice here.
`(setq ,@(-interleave syms (-map #'peval-result-value results))))))))

(`(or . ,exprs)
(let (simple-exprs
current)
(cl-block nil ; dolist is not advised in `ert-runner'
(cl-block nil ; dolist is not advised in `ert-runner'
(dolist (expr exprs)
(setq current (peval--simplify-1 expr bindings))
(cond
Expand Down
41 changes: 34 additions & 7 deletions test/unit-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,18 @@ arguments."
'((x . 1))
'(foo x)))

(ert-deftest peval--setq ()
"Ensure we only evaluate the second argument."
(should-partially-simplify
'(setq x (+ (+ y 1) z))
'((x . 1) (y . 2))
'(setq x (+ 3 z))))
(ert-deftest peval--setq-result ()
"The result of a setq is the assigned value."
;; One assignment.
(should-fully-simplify
'(setq x (1+ 1))
nil
2)
;; Multiple assignments.
(should-fully-simplify
'(setq x (1+ 1) y (1+ 2) z (1+ 3))
nil
4))

(ert-deftest peval--setq-propagate ()
"After evaluating a setq, we know the value of the variable.
Expand All @@ -178,7 +184,28 @@ We should update subsequent references."
(should-partially-simplify
'(progn (setq x (foo)) x)
'((x . 1))
'(progn (setq x (foo)) x)))
'(progn (setq x (foo)) x))
;; Once a variable is unknown, we can't use it in later assignments.
(should-partially-simplify
'(setq x (foo) y x)
'((x . 1))
'(setq x (foo) y x)))

;; (ert-deftest peval--set ()
;; "Correctly evaluate `set'.
;; If we don't know which symbol we're assigning to, we do not know
;; the value of any variable in scope."
;; ;; We don't know the value of x after `set', even though we knew it
;; ;; before.
;; (should-partially-simplify
;; '(progn (set foo 1) x)
;; '((x . 1))
;; '(progn (set foo 1) x))
;; ;; If we do know which symbol we're assigning, proceed as usual.
;; (should-fully-simplify
;; '(progn (set sym 1) x)
;; '((sym . 'x))
;; 1))

(ert-deftest peval--let ()
;; Simplify body.
Expand Down

0 comments on commit 410b5e3

Please sign in to comment.