(defun show (x)
(format nil "~A" x))
(defmacro %tagbody (&body body &aux exprs tags)
(loop :with xs :for x :in body
:if (consp x) :do (push x xs)
:else :collect (nreverse xs) :into @exprs
:and :collect (cons x (gensym (show x))) :into @tags
:and :do (setf xs nil)
:finally (setf exprs (nconc @exprs (list (nreverse xs)))
tags @tags))
`(macrolet ((goto (x) `(return (,(cdr (assoc x ',tags))))))
(block nil
(labels ,(loop :for (tc tn) :on tags :and x :in (cdr exprs)
:collect `(,(cdr tc) nil ,@x
,(and tn `(goto ,(car tn)))))
,@(car exprs) (goto ,(caar tags))))))
(defun factorial (x &aux (f 1))
(%tagbody
0 (if (zerop x) (goto 4))
1 (setf f (* f x))
2 (decf x)
3 (goto 0)
4 (return-from factorial f)))
(format t "Fact(~d) -> ~d" #1=42 (factorial #1#))
KGRlZnVuIHNob3cgKHgpCiAgKGZvcm1hdCBuaWwgIn5BIiB4KSkKCihkZWZtYWNybyAldGFnYm9keSAoJmJvZHkgYm9keSAmYXV4IGV4cHJzIHRhZ3MpCiAgKGxvb3AgOndpdGggeHMgOmZvciB4IDppbiBib2R5CiAgICAgICAgOmlmIChjb25zcCB4KSA6ZG8gKHB1c2ggeCB4cykKICAgICAgICA6ZWxzZSA6Y29sbGVjdCAobnJldmVyc2UgeHMpIDppbnRvIEBleHBycwogICAgICAgICAgICAgIDphbmQgOmNvbGxlY3QgKGNvbnMgeCAoZ2Vuc3ltIChzaG93IHgpKSkgOmludG8gQHRhZ3MKICAgICAgICAgICAgICA6YW5kIDpkbyAoc2V0ZiB4cyBuaWwpCiAgICAgICAgOmZpbmFsbHkgKHNldGYgZXhwcnMgKG5jb25jIEBleHBycyAobGlzdCAobnJldmVyc2UgeHMpKSkKICAgICAgICAgICAgICAgICAgICAgICB0YWdzICBAdGFncykpCiAgYChtYWNyb2xldCAoKGdvdG8gKHgpIGAocmV0dXJuICgsKGNkciAoYXNzb2MgeCAnLHRhZ3MpKSkpKSkKICAgICAoYmxvY2sgbmlsCiAgICAgICAobGFiZWxzICwobG9vcCA6Zm9yICh0YyB0bikgOm9uIHRhZ3MgOmFuZCB4IDppbiAoY2RyIGV4cHJzKQogICAgICAgICAgICAgICAgICAgICAgOmNvbGxlY3QgYCgsKGNkciB0YykgbmlsICxAeCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLChhbmQgdG4gYChnb3RvICwoY2FyIHRuKSkpKSkKICAgICAgICAgLEAoY2FyIGV4cHJzKSAoZ290byAsKGNhYXIgdGFncykpKSkpKQoKKGRlZnVuIGZhY3RvcmlhbCAoeCAmYXV4IChmIDEpKQogICgldGFnYm9keQogICAwIChpZiAoemVyb3AgeCkgKGdvdG8gNCkpCiAgIDEgKHNldGYgZiAoKiBmIHgpKQogICAyIChkZWNmIHgpCiAgIDMgKGdvdG8gMCkKICAgNCAocmV0dXJuLWZyb20gZmFjdG9yaWFsIGYpKSkKCihmb3JtYXQgdCAiRmFjdCh+ZCkgLT4gfmQiICMxPTQyIChmYWN0b3JpYWwgIzEjKSk=