[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tagbody using labels



GO requires no more magic than return-from.

This was an interesting puzzle. This definition doesn't handle go's from
inside an inner tagbody to an outer one, but I couldn't figure out how
to do that without introducing a compiler-let. 

(defmacro tagbody (&rest rest)
  (labels
   ((parse (tail &aux (rest (member-if #'atom (cdr tail))))
       (if tail (cons (cons (gensym) (ldiff tail rest)) (parse rest)))))
   (let ((name (gensym))
        (bodies (parse (cons (gensym) rest))))
    `(block ,name
      (macrolet ((go (tag)
                   `(return-from ,(car (find tag ',bodies :key 'cadr))
nil)))
        (labels
          ,(maplist
            #'(lambda (tail)
             `(,(caar tail) ()
                  ,@(reduce #'(lambda (body tag)
                                 `((block ,(car tag) ,@body)
                                   (return-from ,name (,(car tag)))))
                            bodies
                            :initial-value
                            `(,@(cddar tail)
                              ,(if (cdr tail)
                                  `(return-from ,(caadr tail) nil))))))
            bodies)
           (,(caar bodies))))))))


Larry
<:-)