[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/compat 3257cf6 93/99: Implement TCO for named-let
From: |
ELPA Syncer |
Subject: |
[elpa] externals/compat 3257cf6 93/99: Implement TCO for named-let |
Date: |
Sun, 17 Oct 2021 05:58:03 -0400 (EDT) |
branch: externals/compat
commit 3257cf6a942393e0f2151e3ac65936c52ff06b14
Author: Philip Kaludercic <philipk@posteo.net>
Commit: Philip Kaludercic <philipk@posteo.net>
Implement TCO for named-let
---
compat-28.1.el | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
compat-tests.el | 2 ++
2 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/compat-28.1.el b/compat-28.1.el
index 38d31fa..75396a6 100644
--- a/compat-28.1.el
+++ b/compat-28.1.el
@@ -396,14 +396,72 @@ calling NAME, where the arguments passed to NAME are used
as the new values of the bound variables in the recursive invocation."
:feature subr-x
(declare (indent 2) (debug (symbolp (&rest (symbolp form)) body)))
- (let* ((fargs (mapcar (lambda (b) (if (consp b) (car b) b)) bindings))
- (aargs (mapcar (lambda (b) (if (consp b) (cadr b))) bindings))
- (fn (make-symbol "self"))
- (macro (lambda (&rest args) `(apply ,fn (list ,@args)))))
- `(letrec ((,fn (lambda ,fargs ,(macroexpand-all
- (macroexp-progn body)
- (list (cons name macro))))))
- (apply ,fn (list ,@aargs)))))
+ (let ((fargs (mapcar (lambda (b)
+ (let ((var (if (consp b) (car b) b)))
+ (make-symbol (symbol-name var))))
+ bindings))
+ (aargs (mapcar (lambda (b) (if (consp b) (cadr b))) bindings))
+ rargs)
+ (dotimes (i (length bindings))
+ (let ((b (nth i bindings)))
+ (push (list (if (consp b) (car b) b) (nth i fargs))
+ rargs)
+ (setf (if (consp b) (car b) b)
+ (nth i fargs))))
+ (letrec
+ ((quit (make-symbol "quit")) (self (make-symbol "self"))
+ (total-tco t)
+ (macro (lambda (&rest args)
+ (setq total-tco nil)
+ `(apply ,self (list ,@args))))
+ ;; Based on `cl--self-tco':
+ (tco-progn (lambda (exprs)
+ (append
+ (butlast exprs)
+ (list (funcall tco (car (last exprs)))))))
+ (tco (lambda (expr)
+ (cond
+ ((eq (car-safe expr) 'if)
+ (append (list 'if
+ (cadr expr)
+ (funcall tco (caddr expr)))
+ (funcall tco-progn (cdddr expr))))
+ ((eq (car-safe expr) 'cond)
+ (cons 'cond
+ (mapcar (lambda (branch)
+ (list
+ (car branch)
+ (funcall tco-progn (cdr expr))))
+ (cdr expr))))
+ ((eq (car-safe expr) 'or)
+ (if (cddr expr)
+ (let ((var (make-symbol "var")))
+ `(let ((,var ,(cadr expr)))
+ (if ,var ,(funcall tco var)
+ ,(funcall tco (cons 'or (cddr expr))))))
+ (funcall tco (cadr expr))))
+ ((memq (car-safe expr) '(and progn))
+ (cons (car expr) (funcall tco-progn (cdr expr))))
+ ((memq (car-safe expr) '(let let*))
+ (append (list (car expr) (cadr expr))
+ (funcall tco-progn (cddr expr))))
+ ((eq (car-safe expr) name)
+ (let (sets)
+ (dolist (farg fargs)
+ (push (list farg (pop (cdr expr)))
+ sets))
+ (cons 'setq (apply #'nconc (nreverse sets)))))
+ (`(throw ',quit ,expr))))))
+ (let ((tco-body (funcall tco (macroexpand-all (macroexp-progn body)))))
+ (when tco-body
+ (setq body `((catch ',quit
+ (while t (let ,rargs ,@(macroexp-unprogn
tco-body))))))))
+ (let ((expand (macroexpand-all (macroexp-progn body) (list (cons name
macro)))))
+ (if total-tco
+ `(let ,bindings ,expand)
+ `(funcall
+ (letrec ((,self (lambda ,fargs ,expand))) ,self)
+ ,@aargs))))))
;;;; Defined in files.el
diff --git a/compat-tests.el b/compat-tests.el
index 3c1cf3a..b422c75 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -1219,6 +1219,8 @@ the compatibility function."
"Check if `compat--named-let' was implemented properly."
(should (= (compat--named-let l ((i 0)) (if (= i 8) i (l (1+ i))))
8))
+ (should (= (compat--named-let l ((i 0)) (if (= i 100000) i (l (1+ i))))
+ 100000))
(should (= (compat--named-let l ((i 0) (x 1)) (if (= i 8) x (l (1+ i) (* x
2))))
(expt 2 8))))
- [elpa] externals/compat 598a040 69/99: Add :cond check to lookup-key, (continued)
- [elpa] externals/compat 598a040 69/99: Add :cond check to lookup-key, ELPA Syncer, 2021/10/17
- [elpa] externals/compat b16122b 71/99: Use explicit symbol names instead of alii, ELPA Syncer, 2021/10/17
- [elpa] externals/compat a7d9649 72/99: Manually advise functions when nadvice is not available, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 904d660 74/99: Add documentation to manual advice wrapper, ELPA Syncer, 2021/10/17
- [elpa] externals/compat e689153 76/99: Merge compile and run into one GitHub Action job, ELPA Syncer, 2021/10/17
- [elpa] externals/compat c37e1d1 80/99: Fix quoting in compat-macs' legacy advice installation, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 18c2bf9 83/99: Autoload advised functions is necessary, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 50767a8 90/99: Load deferred code even if file doesn't exist, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 2bb6c10 91/99: Check if function is bound before extracting documentation, ELPA Syncer, 2021/10/17
- [elpa] externals/compat f4c0979 92/99: Prevent shadowing declarations in functional compatibility code, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 3257cf6 93/99: Implement TCO for named-let,
ELPA Syncer <=
- [elpa] externals/compat 347f5a8 94/99: Change version suffix to -rc, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 25879c7 95/99: Require instead of loading compat-*.el files, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 5506770 99/99: Update .elpaignore, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 084f18c 73/99: Declare compat functions used in file-name-with-extension, ELPA Syncer, 2021/10/17
- [elpa] externals/compat db218d0 79/99: Handle top-level JSON objects in Emacs 27.x, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 8981d4b 85/99: Handle multiple signals in string-replace test case, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 8ea6272 86/99: Add define-error compatibility function, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 5d5b215 87/99: Factor out issue with should-error in Emacs 24.3, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 93cee71 88/99: Generate a docstring for manual compatibility advice, ELPA Syncer, 2021/10/17
- [elpa] externals/compat 0a72e60 97/99: Fix the number of expected argument in count-windows :cond check, ELPA Syncer, 2021/10/17