diff options
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | tests/011/exphook.tl | 39 | ||||
-rw-r--r-- | txr.1 | 17 |
3 files changed, 45 insertions, 15 deletions
@@ -5564,13 +5564,13 @@ static val expand_hook_combine_fun(val env, val form, val menv, val type) if (first) { val nform = funcall3(first, form, menv, type); - if (nform) + if (nform != form) return nform; } if (next) { val nform = funcall3(next, form, menv, type); - if (nform) + if (nform != form) return nform; } diff --git a/tests/011/exphook.tl b/tests/011/exphook.tl index 8439ac56..7f745da9 100644 --- a/tests/011/exphook.tl +++ b/tests/011/exphook.tl @@ -2,16 +2,45 @@ (defun-match pico-style-expand-hook ((@(as form (@obj . @rest)) @nil nil) - (if (constantp obj) - ^(quote ,form) - form)) + (let ((*expand-hook* nil)) + (if (constantp obj) + ^(quote ,form) + form))) ((@form @nil @nil) form)) (defmacro pico-style (:env env . body) - (let ((*expand-hook* [expand-hook-combine *expand-hook* - pico-style-expand-hook])) + (let ((*expand-hook* [expand-hook-combine pico-style-expand-hook + *expand-hook*])) (expand ^(progn ,*body) env))) (mtest (pico-style (1 2 3)) (1 2 3) (pico-style (let ((a 0)) (cons a (1 2 3)))) (0 1 2 3)) + +(defun-match infix-expand-hook + ((@(as form (@x @y . @rest)) @nil nil) + (if (fboundp y) + ^(,y ,x ,*rest) + form)) + ((@form @nil @nil) form)) + +(defmacro ifx (:env env . body) + (let ((*expand-hook* [expand-hook-combine infix-expand-hook *expand-hook*])) + (expand ^(progn ,*body) env))) + +(test + (ifx (let ((a 1) (b 2) (c 3)) + (- ((a + b) * 3)))) + -9) + +(test + (ifx + (pico-style + ((1) cons (2)))) + ((1) . (2))) + +(test + (pico-style + (ifx + ((1) cons (2)))) + ((1) . (2))) @@ -44087,16 +44087,17 @@ rather than assign a value to it. Assigning an incorrect value to to it in a Listener session may be difficult to recover from, since it may render the Listener incapable of evaluating forms. -Note: it is recommended to capture the previous value of +Note: it is recommended for a hook to have access to the previous value of .code *expand-hook* -and call that function before performing any transformation of +and call that function in cases where +.meta form +the hook would decline to perform a transformation by returning .metn form . -If that function performs a transformation, indicated by -returning a different form, then return that form, only -performing local processing when that function has declined. The function .code expand-hook-combine -is provided which encapsulates this logic. +is provided which encapsulates this logic. It allows a hook to easily +insert itself before the other hooks, as recommended above, or +after the other hooks. .TP* Example @@ -44116,8 +44117,8 @@ is provided which encapsulates this logic. ;; hooks are tried first. (defmacro pico-style (:env env . body) - (let ((*expand-hook* [expand-hook-combine *expand-hook* - pico-style-expand-hook])) + (let ((*expand-hook* [expand-hook-combine pico-style-expand-hook + *expand-hook*])) (expand ^(progn ,*body) env))) ;; Under pico-style, (1 2 3) converts to '(1 2 3) |